Boost logo

Boost Users :

Subject: [Boost-users] dev_poll_reactor vs. strand and async_write
From: Chris Hite (C.Hite_at_[hidden])
Date: 2009-06-04 05:47:06


In a project using asio I noticed performance issues on Sun vs. Linux.
It turned out that dev_poll_reactor is doing tones of system calls
always pairs of write() and ioctl(). Stranger still is that the calls
to write() are for 0 bytes.

I was able to avoid the issue by switching from strand to mutex. I
think there is some bug or logic error in dev_poll_reactor so I wrote a
test program to narrow down when it happens:

//

Christopher Hite

 
RTS Realtime Systems Software GmbH, Rembrandtstrasse 13, D-60596 Frankfurt am Main
T: +49.69.61009.0 / F: +49.69.61009.181

Sitz: Frankfurt am Main - HRB 84467 Amtsgericht Frankfurt am Main
Geschäftsführer: Steffen Gemuenden, Igor Sluga

www.rtsgroup.net

This email and any attachments are for the exclusive and confidential use of the intended recipient. If you are not the intended recipient, or an employee or agent responsible for delivering this message to the intended recipient, please do not read, distribute or take action in reliance upon this message. If you have received this in error, please notify me immediately by return email and promptly delete this message and its attachments from your computer system.
-------------------------------------------------------------------------------
#include <boost/asio.hpp>
#include <iostream>

using namespace boost::asio;

io_service service;
io_service::strand strand_(service);
local::stream_protocol::socket s0(service);
local::stream_protocol::socket s1(service);

void wh(const boost::system::error_code& ec,const std::size_t){
    if(ec)
        std::cout<<ec; //never happens
}

void sendAByte(){
    static char sendBuf[256];
    async_write(s0,buffer(sendBuf,1),wh);
}

int main(){
    local::connect_pair(s0,s1);

    std::cout<<"dispatching\n";
    for(int i=0;i<100000;i++)
#if 1
        strand_.dispatch(sendAByte);
#else
        sendAByte(); //doesn't cause the sys calls
#endif

    std::cout<<"waiting on run to finish\n";
    service.run();
    return 0;
}
//-------------------------------------------------------------------------------

Here are some dtraces to help analyze what's going on $XX is the
executable. This one shows all the calls to write() with size=0.
async_write uses sendmsg() so all these are attributable to
dev_poll_reactor.

dtrace -n 'syscall::write:entry/pid==$target&&arg2==0/{ ustack(); }' -c $XX

  0 5467 write:entry
              libc.so.1`_write+0x8
              
strandtest`__1cFboostEasioGdetailQdev_poll_reactor4b_Drun6Mb_v_+0x1b4
              
strandtest`__1cFboostEasioGdetailPtask_io_service4n0CQdev_poll_reactor4b___Gdo_one6Mrn0CLscoped_lock4n0CLposix_mutex___pn0EQidle_thread_info_rn0AGsystemKerror_code__I_+0x204
              
strandtest`__1cFboostEasioGdetailPtask_io_service4n0CQdev_poll_reactor4b___Drun6Mrn0AGsystemKerror_code__I_+0xa8
              strandtest`main+0xe8

This one counts the system calls. What's very disturbing is that the
longer you let it run the more sys calls are made. Why doesn't the
system block waiting for the socket to become write-able again (which it
won't)?

dtrace -n 'syscall:::entry/pid == $target/ { @num[probefunc] = count();
}' -c $XX
  fcntl 6
  brk 2474
  sendmsg 21505
  ioctl 60194
  write 60195
  lwp_sigmask 120382

Similar testing on Linux(x86) using strace doesn't show so many system
calls (except a few for locking mutexes).

Perhaps Christopher Kohlhoff or whoever implemented the thing can take a
look. I'm guessing there some event which keeps getting detected but
isn't processed. Would someone please take a look or do I need to debug
it myself?


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net