[reSIProcate] Transport TxFifo draining: timing

Kennard White kennard_white at logitech.com
Fri Nov 19 17:56:46 CST 2010


Hi,

One of the key issues I'm facing in extending resip/repro to handle many
connections is the why the stack Transport's drain their TxFifo queues. The
flow today is:

   - When data is ready to send from transaction layer, the message is added
   to the Transport's TxFifo queue.
   - Prior to calling select(), the hasDataToSend() query is run on all
   internal Transports. This is O(#transports).
   - After select returns (with zero timeout), process() is called on all
   internal Transports. Each transport checks its TxFifo queue.

With the epoll() patch in place, these two O(N) traversals for the TxFifo
appear to be driving factors. Aside from performance issues, this is another
obstacle to libevent migration. I can think of a few things to do about
this:

   - Keep a list queue of Transports with data to transmit. As data is added
   to TxFifo, append the Transport to queue. This would solve the O(N) problem.
   The work is non-trivial low-level queue stuff with reasonable chance of
   bugs, especially if implemented with performance in mind.
   - InternalTransport::transmit(), which posts to data to the queue, could
   also call a method of Transport to do "something" with the data. There are
   two somethings that could happen:
      - Request callback on socket writable, and in that callback (from
      epoll, etc.) would then try draining the queue. This is what I ended up
      doing with UdpTransport: see checkTransmitQueue().
      - Read from the queue immediately and try writing the message onto the
      wire. If the write fails, then need to stash this "working" message and
      request writable callback. This approach is the preferred style
when working
      with edge-triggered epoll.

Is there any particular reason not to try writing the data immediately when
posted to the queue? Issues I can think of:

   - Threads. I'm concerned only with the InternalTransports which all run
   within the same thread as the stack itself. As far as I know, no other
   threads post to the transmit queue. Is that true?
   - Fairness. Defering the write until after returning to the main loop
   would allow some sort of prioritization to take place. But as far as I can
   tell there isn't any code in place to enforce fairness or prioritization.
   - Recursion. Some transports post messages to their own TxFifo; would
   need to careful about recursion; ideally avoid it. I suspect recursion
   safety is relatively simple to implement.


Any other approaches? Preferences? Risks?

Thanks,
Kennard
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://list.resiprocate.org/pipermail/resiprocate-devel/attachments/20101119/58062af3/attachment.htm>


More information about the resiprocate-devel mailing list