Performance Optimization ========================================= .. contents:: Table of Contents :depth: 3 Maximising performance --------------------------- There are few configuration settings to tweak to reduce the CPU usage of the application or to produce the best performance out of pjsip: Echo canceller ~~~~~~~~~~~~~~~~~~ The software AEC probably is the most CPU intensive module in PJSIP. To reduce the CPU usage, shorten the EC tail length to lower value (the :cpp:any:`pjsua_media_config::ec_tail_len` setting), or even disable it altogether by setting it to zero. Float vs fixed point ~~~~~~~~~~~~~~~~~~~~~~~ If the platform does not support floating point, disable floating point in PJSIP build, by declaring :c:macro:`PJ_HAS_FLOATING_POINT` to 0 in :any:`config_site.h`. Codec ~~~~~~~~~~~~~~ Use low complexity codecs such as *pcmu* or *pcma*. When using *pcmu* or *pcma*, make sure pjmedia chooses the table based implementation, by setting :c:macro:`PJMEDIA_HAS_ALAW_ULAW_TABLE` macro to 1 (this is default). Avoid resampling ~~~~~~~~~~~~~~~~~~~ Resampling is a CPU intensive process, thus it should be avoided, by choosing uniform clock rate for all media components (sound device, conference bridge, codecs, WAV files, etc.). Choose effective sampling rate ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Make sure that PJSUA-LIB selects the most effective sampling rate/clock rate for the application. For example, if the application only supports narrowband codecs (G.711, GSM, iLBC, G.723, or G.729), then the best sampling rate to choose would be 8KHz. Choosing higher sampling rate will only just waste CPU power due to resampling and more processing in general. With *pjsua*, sampling rate can be forced with ``--clock-rate`` option. In the application, this can be achieved by setting :cpp:any:`pjsua_media_config::clock_rate` field. Conference bridge vs audio switchboard ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ If conferencing feature is not needed, replace the conference bridge with the :any:`Audio Switchboard ` that is lighter and has less latency. To use the audio switchboard, declare :c:macro:`PJMEDIA_CONF_USE_SWITCH_BOARD` to non-zero in :any:`config_site.h`. See :any:`Audio Switchboard ` for more information. Logging ~~~~~~~~~~~~~~~~ Speeding up logging can be achieved in two ways. First is to make sure that the log writer callback function that is registered to PJLIB logging writes the log as quick as possible. The default log writer callback is to print the log to stdout, hence the performance depends on the performance of the terminal. Application can supply its own log writer callback by calling :cpp:any:`pj_log_set_log_func()` function. The callback can control what gets written by filtering the log level of the message. The second way is to control what gets written to the log in the first place, by setting the logging (verbosity) level, which ranges from 1 (fatal error) to 5 (verbose debug). The default logging level is 5 to provide verbose information to assist debugging. Logging level can be changed at run-time with :cpp:any:`pj_log_set_level()`. When absolute performance is needed, application can disable, at compile time, all logging calls with verbosity greater than certain limit by setting :c:macro:`PJ_LOG_MAX_LEVEL` macro to the desired level in :any:`config_site.h`. Threads ~~~~~~~~~~~~~~~~ Use the optimum number of SIP worker threads in the application. The optimum number would be equal to the number of processors (or processor cores) in the system. Run-time checks ~~~~~~~~~~~~~~~~~~ The libraries are equipped with run-time checks to prevent bad parameters from crashing the software. This feature can be disabled by setting :c:macro:`PJ_ENABLE_EXTRA_CHECK` to 0. Stack checks ~~~~~~~~~~~~~~~~~~~ PJLIB is equipped with stack overflow detection. This feature can be disabled by setting :c:macro:`PJ_OS_HAS_CHECK_STACK` to 0. Safe module ~~~~~~~~~~~~~~~~~~~ PJSIP is equipped with mutex protection to protect PJSIP modules from being unregistered while they are still being accessed by PJSIP. If the application doesn't add/remove modules dynamically during run-time, you can disable this protection by setting :c:macro:`PJSIP_SAFE_MODULE` to 0. Unescape in-place ~~~~~~~~~~~~~~~~~~~~~~~~~ By default, PJSIP will make a copy of escaped message sequence before unescaping it. You can configure PJSIP to unescape *in-place* by setting :c:macro:`PJSIP_UNESCAPE_IN_PLACE` to 1. Note that unescaping in place will modify the original message, so don't do this if the application needs to access the original message after it has been parsed (pjsip does not need this access). Hash tolower Optimization ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ By setting :c:macro:`PJ_HASH_USE_OWN_TOLOWER` to one, the hash function will convert the key to lower case and calculate the hash value in one loop. Release mode ~~~~~~~~~~~~~~~~~~ Don't forget to set the appropriate compiler optimization flag, and disable assertion with ``-DNDEBUG``. How to configure pjsip to serve thousands of calls ------------------------------------------------------- There are few settings to tweak: #. First apply the CPU reduction techniques above to maximize the performance. #. Do not use PJSUA-LIB. PJSUA-LIB is designed for building client application. #. By default, PJSIP is configured to handle only limited simultaneous SIP transactions and dialogs. This can be enlarged according to the requirement, by setting both :c:macro:`PJSIP_MAX_TSX_COUNT` and :c:macro:`PJSIP_MAX_DIALOG_COUNT` to the appropriate values (for example, ``640*1024-1``). #. If large number of TCP/TLS connections are needed, increase :c:macro:`PJ_IOQUEUE_MAX_HANDLES` to some large number (the default is only 64). #. We've found that the simple GUID generator (used by GNU build system for \*nix and MacOS X) will produce duplicate Id after approximately 2^14 generations. This would cause things like transactions to have duplicated branch as previous transactions! On Linux, the ``./configure`` script will detect the presence of ``libuuid`` (part of `e2fsprogs `__) and use it if available, to avoid this problem. If you encounter this problem, please check if ``libuuid`` is available for ``./configure`` on your system. If you are using PJSUA-LIB, then the maximum number of calls supported is configurable from :cpp:any:`pjsua_config::max_calls` (default is 4). When increasing the limit, compile time options :c:macro:`PJSUA_MAX_CALLS` and :c:macro:`PJ_IOQUEUE_MAX_HANDLES` also needs to be changed accordingly (set the later to approximately 3 times :c:macro:`PJSUA_MAX_CALLS`). More info can be found `here `__.