[ANN] Ebb Web Server

Marc Lehmann schmorp at schmorp.de
Wed Apr 2 21:11:25 CEST 2008


On Mon, Jan 14, 2008 at 06:02:43PM +0100, ry dahl <ry at tinyclouds.org> wrote:
> I'm writing a web server called Ebb. It's written in C, makes use of

Hi, I just read your "benchmark" page at
http://four.livejournal.com/847870.html

As I see, your primary problem is letting ruby coroutines get some cpu
time in a reasonable way while also running the ev event loop.

As I wrote the coroutine package for perl, I likely faced the same
problems (or at least very similar ones).

Your problem boils down to: let other coroutines run as long as they are
ready, otherwise make sure you block the process.

Here is how I solve the problem for the "Event" library (ignore it first):

   http://cvs.schmorp.de/Coro/Event/Event.xs

and here is how I solved it for EV=libev:

   http://cvs.schmorp.de/Coro/EV/EV.xs

the basic algorithm is to let whoever thinks is the main thread run
ev_loop, while Coro links itself into the event system by use of an idle
watcher, and a prepare watcher.

The prepare watcher is always active and basically does this:

1. cede=yield to one other coroutine, regardless of priority

2. then cede=yield to other coroutines of same and higher priority (incede
   is simply the number of instances running ev_loop (Coro allows multiple
   event loop calls running at the same time on the same loop, so does ev),
   and cede returns wether there was another coroutine available to switch to.

3. if there are any "ready" coroutines left by now, then they must be of
   lower priority than the one running ev_loop. in that case, start an idle
   watcher to keep the loop from blocking.

the idle watcher does nothing but stop itself, it is only used to make
ev_loop non-blocking.

The overall result of this not-totally-obvious algorithm is:

- as long as there are coroutines of the same or higher priority than the
  one running the event loop, the event loop will NOT be called
  (those inhibit collecting events).

- if there are coroutines ready of lower priority, then always run one such
  coroutine for a while but also poll for events regularly.

- if no other coroutine is ready, block in the event loop till more events
  arrive.

- no special ev_loop wrapper is required, any coroutine can run the mainloop,
  and priorities fully decide wether a coroutine inhibits event collection
  or not, and the prepare watcher can fully decide wether to block
  or not.

This seems to be a very workable model. Of course, both the perl coroutine
package and libev have been designed to allow just that. I don't know about
ruby's coroutines, but the following features are required:

- you need the ability to find out how many other coroutines are runnable
- you need a way to know the relation of the coroutine executing ev_loop
  to the other coroutines (higher, lower priority).

If you have that, you can integrate ev "synchronously" into ruby, without
having to do intra-thread communications.

If ruby has no priorites, then it becomes even simpler:

- in the prepare watcher, as long as other coorutines are ready,
  switch to them (either endlessly or a number of times, such as once
  though all of them)
- then block once.

-- 
                The choice of a       Deliantra, the free code+content MORPG
      -----==-     _GNU_              http://www.deliantra.net
      ----==-- _       generation
      ---==---(_)__  __ ____  __      Marc Lehmann
      --==---/ / _ \/ // /\ \/ /      pcg at goof.com
      -=====/_/_//_/\_,_/ /_/\_\



More information about the libev mailing list