[bind10-dev] ASIO and asyncore, was Re: Question about config channel and another msgq channel

Shane Kerr shane at isc.org
Wed Jun 30 11:23:35 UTC 2010


Fujiwara-san,

On Wed, 2010-06-30 at 18:58 +0900, Kazunori Fujiwara wrote:
> Hi, Shane,
> 
> Thanks very much for your explanation about asyncore.
> 
> Currently, BIND 10 components uses variours models to implement
> asynchronous I/O.
> 
>   C++ code: using ASIO
>   bind10:   select.select
>   msgq:     select.poll or select.kqueue
>   cfgmgr:   blocks at self.cc.group_recvmsg(False)
>   cmdctl:   select.select + polling
>   xfrin:    thread + asyncore
>   xfrout:   thread + blocking
> 
>   statistics: trying to use select.select
> 
> Then, do we consider these differences are OK?

Interesting. :)

Regarding select.select vs. select.poll/select.kqueue... poll() is
usually more efficient than select(), and the other polling mechanisms
are more efficient than those two in general, but are non-portable.

For some reason the Mac implementation of select does not support
select.poll, so although bind10 was using select.poll, I converted to
select.select since it is universally supported, and bind10 only has a
very few file descriptors. msgq uses either select.poll or
select.kqueue, although I am not sure of the motivation for this;
perhaps based on the possibility that we will have dozens of connections
to the process?

In general, I tend to follow the following guidelines for deciding on
I/O processing:

     1. If possible, just block. That is what cfgmgr does.
     2. If you have a single logic flow, but need to handle more than
        one type of input, use select.(select|poll|whatever). This is
        what bind10 does - it gets either a command-channel command, or
        a process dies, or it gets a fatal signal, or a timer expires.
        Each of these events is processed to completion.
     3. If you have separate logic flows, then use threads and block in
        each if possible. By "separate logic flows" I mean that you have
        state about what is going on in concurrent operations. Threaded
        code is usually simpler to read and understand in this case, and
        this is what xfrout does.
     4. If you have separate logic flows, but need to be very high
        performance or have a *lot* of concurrent actions, or other
        special requirements, then use something like asyncore. It's a
        bit of a hassle to have to follow a state machine to understand
        the code, but unavoidable (until the world switches to Apple's
        magic new parallelism invention).

If you are curious, there is an aging-but-still-accurate analysis of the
various techniques of waiting for input here:

http://www.kegel.com/c10k.html

I also found a short, Python-specific blog entry here:

http://ionelmc.wordpress.com/2008/04/01/curious-difference-between-epoll-poll-kqueue-and-select/

Now, as for whether this is okay in BIND 10... I don't know. Having "One
True Way" might make it easier to understand and figure out the system.
OTOH it would mean we would sometimes have to implement a more
complicated mechanism than necessary.

Personally I am okay with having separate approaches for now, and
perhaps refactoring to a more consistent approach later, but of course
other opinions may vary!!!

--
Shane




More information about the bind10-dev mailing list