Re: ANN: Etiquette: a protocol construction tool

Peter Seibel <[email protected]> 17 Sep 2003 21:27:20 -0700
Newsgroups gmane.lisp.clump
Message-ID <[email protected]>
Luke Gorrie <[email protected]> writes:

> A variation is to have a thread pool of a fixed maximum size, but
> this is not very robust. It assumes you will never have to block on
> more than N connections at a time, which breaks down with
> slow/unreliable clients and with DoS attackers.

Another variant (which worked quite successfully in a message
processing system I worked on in Java) is to use a fixed number of
threads to provide an asynchronous interface to things that are
fundamentally blocking. Thus you have one thread devoted to running
your state machines (or possibly N threads, where N is the number of
CPU's in your machine) and then you use one thread to deal with each
place you have to blocking i/o. For instance, if you don't have
select(), either because it's not exposed up through Lisp or because
the OS implements it badly[1], or because you're dealing with some
other API that doesn't expose itself as a filehandle, such as doing
queries against a database, you can instead spin up a thread that
accepts requests to do i/o on a queue and does the i/o as fast as it
can. When each piece of i/o finishes, the state machine that submitted
the i/o request goes back into the bin to be run by the state machine
execution thread. (Actually, at each place where you need to call
blocking APIs you want to use as many threads as you need, hopefully a
small number, to keep the i/o going at full bandwidth. At least if
you're blocked on i/o, which you should be in this kind of system.)
The nice thing about implementing a system this way is that all those
queues show you exactly where your bottlenecks are--whichever queue
backs up is the bottleneck.[2]

Another nice feature of this architecture is that, there may be i/o
that the state machine doesn't have to wait for. For instance, if the
protocol requires data to be durably written to disk (such as a
transaction log) it may be able to enqueue write requests as it goes
along that it doesn't have to wait for and then finally a flush
request that it does. If the i/o subsystem is cranking away writing
stuff to disk as fast as it can and flushing whatever it's written
anyone asks it to, any given request to flush may return immediately
if another flush request already caused the data to be flushed.

So, to echo Luke's point, it would be great to have a tool that lets
me generate the protocol state machine for an arbitrary protocol in
such a way that I can somehow plug in the actions it should do when it
needs to interact with the outside world (i.e. do potentially blocking
i/o) and provide some way to "suspend" the state machine and
"continue" it when the i/o completes.

-Peter

[1] As the C10k page Luke cited <http://www.kegel.com/c10k.html>
points out, select() and poll() have their own scaling problems.

[2] c.f. Little's Law.

-- 
Peter Seibel                                      [email protected]

         Lisp is the red pill. -- John Fraser, comp.lang.lisp