[asterisk-dev] [Code Review] Avoid wasteful frame queue traversals in chan_iax2 network_thread()

Russell Bryant russell at digium.com
Sat Mar 28 23:57:53 CDT 2009


-----------------------------------------------------------
This is an automatically generated e-mail. To reply, visit:
http://reviewboard.digium.com/r/212/
-----------------------------------------------------------

(Updated 2009-03-28 23:57:53.607625)


Review request for Asterisk Developers.


Summary
-------

While doing some profiling for <http://reviewboard.digium.com/r/205/>, one function that caught my eye was network_thread() in chan_iax2.c.  After the things that I was working on there, it was the next target for analysis and optimization.  I used oprofile's source annotation functionality and found that the loop traversing the frame queue in network_thread() was to blame for the excessive CPU cycle consumption.

The frame_queue in chan_iax2 previously held all frames that either were pending transmission or had been transmitted and are still pending acknowledgment.

In network_thread(), the previous code would go back through the main for loop after reading a single incoming frame or after being signaled because a frame had been queued up for initial transmission.  In each iteration of the loop, it traverses the entire frame queue looking for frames that need to be transmitted.  On a busy server, this could easily be quite a few entries.

This patch is actually quite simple.  The frame_queue has become only a list of frames pending acknowledgment.  Frames that need to be transmitted are queued up to a dedicated transmit thread via the taskprocessor API.

As a result, the code in network_thread() becomes much simpler, as its only job is to read incoming frames.


Diffs (updated)
-----

  /trunk/channels/chan_iax2.c 184835 

Diff: http://reviewboard.digium.com/r/212/diff


Testing
-------

I used a similar test that I used in R205 for this.  I sent 15000 IAX2 registrations evenly spaced out over 1 minute.  The server was configured using realtime with a MySQL backend via res_config_odbc.  IAX2 realtime caching was enabled.  I ran the test, used oprofile, and watched CPU usage.

The box has an Intel Core 2 Duo @ 2.33 GHz and 2 GB of RAM.  The noted CPU consumption is out of 200%, since it's a dual core machine.

----------------------------

Asterisk SVN-trunk-r184801 built by russell @ milo on a x86_64 running Linux on 2009-02-12 19:26:12 UTC

Average CPU usage by Asterisk: 10 to 15%

(results below 0.5% omitted)

samples  %        image name               app name                 symbol name
33690    39.8500  chan_iax2.so             chan_iax2.so             network_thread
13263    15.6881  chan_iax2.so             chan_iax2.so             socket_process
6972      8.2468  chan_iax2.so             chan_iax2.so             __attempt_transmit
6618      7.8281  chan_iax2.so             chan_iax2.so             pvt_destructor
6542      7.7382  chan_iax2.so             chan_iax2.so             __find_callno
2037      2.4095  asterisk                 asterisk                 internal_ao2_callback
620       0.7334  asterisk                 asterisk                 sched_time_cmp
602       0.7121  asterisk                 asterisk                 handle_statechange
563       0.6659  [vdso] (tgid:7462 range:0x7fffe31fe000-0x7fffe3200000) asterisk                 (no symbols)
555       0.6565  chan_iax2.so             chan_iax2.so             peer_cmp_cb
518       0.6127  asterisk                 asterisk                 internal_ao2_ref
...

----------------------------

Asterisk SVN-russell-iax2_transmit_q-r184836-/trunk built by root @ milo on a x86_64 running Linux on 2009-03-29 03:43:13 UTC

Average CPU usage by Asterisk: 5 to 10%

(most results below 0.5% omitted)

samples  %        image name               app name                 symbol name
9290     24.5969  chan_iax2.so             chan_iax2.so             socket_process
6553     17.3502  chan_iax2.so             chan_iax2.so             __find_callno
3630      9.6111  chan_iax2.so             chan_iax2.so             pvt_destructor
2392      6.3332  chan_iax2.so             chan_iax2.so             __attempt_transmit
1946      5.1524  asterisk                 asterisk                 internal_ao2_callback
582       1.5409  asterisk                 asterisk                 handle_statechange
557       1.4748  chan_iax2.so             chan_iax2.so             peer_cmp_cb
528       1.3980  asterisk                 asterisk                 internal_ao2_ref
523       1.3847  [vdso] (tgid:3088 range:0x7fff3c3fe000-0x7fff3c400000) asterisk                 (no symbols)
478       1.2656  asterisk                 asterisk                 sched_time_cmp
416       1.1014  res_config_odbc.so       res_config_odbc.so       realtime_odbc
348       0.9214  chan_iax2.so             chan_iax2.so             register_verify
339       0.8976  chan_iax2.so             chan_iax2.so             build_peer
320       0.8473  chan_iax2.so             chan_iax2.so             .plt
291       0.7705  asterisk                 asterisk                 __bt_defcmp
236       0.6249  asterisk                 asterisk                 _ast_heap_remove
233       0.6169  asterisk                 asterisk                 .plt
221       0.5851  asterisk                 asterisk                 __ao2_iterator_next
216       0.5719  asterisk                 asterisk                 tps_processing_function
204       0.5401  asterisk                 asterisk                 ast_get_channel_tech
193       0.5110  chan_iax2.so             chan_iax2.so             iax2_process_thread
190       0.5031  asterisk                 asterisk                 ast_hashtab_remove_this_object
...
56        0.1483  chan_iax2.so             chan_iax2.so             transmit_frame
...
36        0.0953  chan_iax2.so             chan_iax2.so             network_thread
...

----------------------------


Thanks,

Russell




More information about the asterisk-dev mailing list