Measuring performance in Asterisk, like most software systems for that matter, can be a complicated task. When testing performance it is important to define goals, and limit the context for that which is being tested. It’s been previously shown that res_pjsip might have an efficiency problem when it comes to inbound registration.
Our main goal for this round of testing was to check the performance in res_pjsip with regards to inbound registration. We wanted to find out how much CPU was being used, and where its time was being spent. As well, we desired to monitor memory usage. Lastly, we also wanted to compare the res_pjsip results to chan_sip to see how they stacked up. We would then be able to ascertain whether or not there was a real performance issue.
Unit Under Test
It’s always worth mentioning the kind of system, and hardware the tests are run on. While the test results are relative to my environment I would expect them to scale accordingly. All testing discussed here was run using 64-bit Ubuntu 14.04, and the following hardware:
1 socket, 2 core, 2 threads per core Intel(R) Core(TM) i3-2330M CPU @ 2.20GHz
256 GB 6 GB/s SATA III SSD
8 GB RAM
This means the operating system effectively “sees” 4 CPUs. All CPU percentages mentioned, or shown below are the averages of CPU percentages across all CPUs (i.e. total CPU percentage divided by 4).
Since we limited the testing to inbound registration we also only loaded those modules that were required for Asterisk to execute and handle the test scenario. Speaking of which, all tests were driven by a SIPp scenario from another machine over a local network. You can find the scenario, and configuration files used during testing here. All tests were run for a minimum of 5 minutes.
The Way Things Were
The process of making improvements to inbound registrations in res_pjsip did not happen overnight. Changes were made incrementally, and spread across several different Asterisk releases. So let’s first go back a release or two, prior to any performance patches, so we can see how those changes have boosted run times and lowered memory consumption. Below are the results from testing with Asterisk 13.21.1:
As you can see, strictly looking at CPU and memory, chan_sip appears to make better use of system resources. However, notice how there is no data for chan_sip at the 350 mark. The reason for that is chan_sip became consumed with retransmissions (~98%) after a minute or two into the test. res_pjsip on the other hand, while using a little more system resources, was able to easily handle 350 registrations per second. As a matter of fact it was able to manage much more than that (a bit on that later).
Recent Performance Improvements
As a program advances it is not unusual for it to consume more resources. However, it’s important to know whether expended resources are justified. So after more testing, and some code analysis it was discovered that there were a few places that could be improved upon in res_pjsip.
The change that had the most dramatic effect on CPU usage for registrations in res_pjsip was the OPTIONS rewrite patch. You might wonder why that might have such an effect on registrations. It’s because that’s the part of the code that handles state (aggregation, publishing, etc) for contacts, AoRs, and endpoints. So every time an endpoint registers, updates its registration, or unregisters that part of the code is exercised. You can read more about that particular change here. This patch was released in Asterisk 13.22.0 and 15.5.0.
Another recent modification that also improved performance targeted the actual res_pjsip inbound registration handling routines. This refactoring removed a costly redundant database lookup. As well it too reduced excessive “pool” allocations down to one. This patch will be released in Asterisk 13.23.0, 15.6.0, and 16.1.0.
The last change I’ll mention that enhanced res_pjsip's effectiveness is one that reduced processing when a contact is updated. Prior to this patch every time a registration was refreshed a ContactStatus AMI event would be issued. However, there was no material change to the underlying contact and AoR. So this functionality could be safely removed. This revision will go out in Asterisk 16.0.0+.
How Things are Now
With some of those improvements now applied, let’s see how the current 13 branch, or what will become 13.23.0, of Asterisk now fares:
It now appears res_pjsip has a slight edge in CPU. However, memory usage is still a little higher. Asterisk 16.0.0 should have similar results since it too contains a few of the improvement patches.
How Things will be
You’ll have to wait until Asterisk 16.1.0 though to get the benefit of all the enhancements. Let’s take a look at how things will run under 16.1.0:
Not only has CPU consumption been lowered even more, memory usage has also decreased in res_pjsip.
Max Registrations Per Second
As noted, each test shows chan_sip unable to handle too much more than 300 registrations per second. At, or around the 350 mark there are just too many retransmissions for chan_sip to handle. res_pjsip on the other hand was able to deal with much more than that. In fact with all enhancement patches applied res_pjsip was able to easily process 2000 registrations per second. And with minimal retransmissions. Even processing 2500 registrations per second resulted in only a 1-2% retransmission rate.
It’s evident that in the past res_pjsip suffered some when it came to inbound registrations. However, the inefficiencies have been addressed. It can now run on par, if not better than chan_sip (CPU-wise at least). System resource management talk aside though, it’s apparent that res_pjsip is far superior at handling more registrations per second than chan_sip . Which I contend would be what most people would want out of their SIP registrar.