[ANN] Ebb Web Server

Tony Arcieri tony at medioh.com
Wed Apr 2 21:40:31 CEST 2008

On Wed, Apr 2, 2008 at 1:11 PM, Marc Lehmann <schmorp at schmorp.de> wrote:

> 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.

Unfortunately as far as I can tell Ruby 1.8 doesn't provide granular entry
points into the schedule that would allow for that sort of thing.  Ruby 1.9
uses native threads so it's not an issue... you can make calls that block
indefinitely with rb_thread_blocking_region().

When adding Ruby 1.8 support to Rev, I used the following approach for a
"oneshot" style function:

- Create an ev_timer which fires every 10ms (according to the author of
EventMachine this is Ruby's scheduler quantum)
- Activate Ruby's signal handling for a blocking system call (TRAP_BEG).
- Call ev_loop(..., EVLOOP_ONESHOT).  Rev is already set up to buffer
incoming events in an exponentially growing array.
- Restore normal Ruby signal handling (TRAP_END).
- Schedule the next thread with rb_thread_schedule()
- Loop unless we received events other than the 10ms ev_timer
- Otherwise rb_funcall the event responders, and return

This approach has been working fine for me and does not seem to negatively
impact Ruby 1.8's thread scheduler.  However as it is looping making a
system call every 10ms it does seem to chew up more CPU than I like.  I
haven't played around with making libev block for longer periods of time (I
think Ebb blocks every 100ms?) but it might be possible to go higher without
adversely affecting Ruby's thread scheduling.

I'm CCing ruby-core to see if anyone there has any input...

Tony Arcieri
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.schmorp.de/pipermail/libev/attachments/20080402/eb45916b/attachment.html>

More information about the libev mailing list