On Fri, Apr 25, 2008 at 11:40:03PM -0400, Uri Guttman <[EMAIL PROTECTED]> wrote:
> check out stem's pure perl event loop. there are examples in the

Maybe I'll provide a backend for stem.

> modules. it does things in a different direction and doesn't scan
> select's bit masks but instead it scans the interesting handles and see
> whether their bits are set. it should exhibit good behavior under growth
> as all the data are managed in hashes.

That is exactly as the anyevent perl backend did in the previous
version. I don't see how that should exhibit good behaviour - file
descristpors are small integers, so hashes only add overhead over arrays,
and checking every file descriptor that way is much slower than scanning
the bitmask.

Especially in the important case of many handles/few active ones, an approach
of "scan all handles" is very slow.

(The benchmarks reflect this, you could try with an older anyevent
release where we just check the keys of the hash storing fd information:
performance is much lower).

>   ML> I then made a second benchmark, designed not to measure anyevent 
> overhead,
>   ML> but to measure real-world performance of a socket server.
> 
> and that /sessions code also shows use of the asyncio module. if you can
> benchmark that i would be interested in the results. 

Hmm, tt seems to have become fashionable lately to call synchronous I/O
asynchronous (see IO::Async, another 100% synchronous framework). What
exactly is asynchronous about the I/O in that example, it seems to be
fully synchronous to me (just event-driven).

>   ML> For small servers, the overhead introduced by running a lot of perl
>   ML> opcodes per iteration dominates, however, reflected in the last 
> benchmark.
> 
> in a heavily loaded server most of the work in in the i/o and should
> overwhelm the event loop itself. that is the whole purpose of event
> loops as we all know here. 

I actually don't know that. When I write response data (such as a file in
my anime server), the performance of the event loop completely dominates
(ignoring IO::AIO overhead in this case, which also of coruse relies on
the event loop).

Of course, select/poll don't scale at all, unless the majority of handles
is active, also not very typical of heavily loaded servers.

>   ML> However, the net result is that the pure perl event loop performs
>   ML> better than almost all other event loops (EV being the only exception)
>   ML> ins erious/medium-sized cases, while I originally expected it to fail
>   ML> completely w.r.t. performance and being only usable as a workaround when
>   ML> no "better" event module is installed.
> 
> i don't find that surprising. perl's i/o is decent and as i said above,
> a loaded server is doing mostly i/o. 

Well, since the server in this benchmark hardly does anything, and as you
can see by the results, the event loop completely dominates, and bad event
loops are a thousand times slower than good ones.

When put into requests/s, this means that with POE, you are limited
to <1000 requests/s, while with EV you can easily reach hundreds of
thousands.

Also, this does not explain at all why Event is so slow, and why Glib scales
so extremely badly. Most of the stuff that slows down the perl-based event
loop is clearly stuff that is much much faster in C.

For a reasonable event loop implemented in C, the overhead of calling
select should completely dominate the rest of the processing (it does so in
EV).

This is not the case for any of the event loops I tested with the
exception of EV and Event (which "only" has high overhead, but it doesn't
grow beyond reason).

> i will take a gander and see if i can play with it and add stem's loop
> to it. if you want to work on this with me, i wouldn't mind the help.

Well, can't say thereis much demand for it, but if you cna give me a pointer
on these things in the docs I can probably come up with one before the next
release:

- how can I do one iteration of the event loop? This is important
  for condvars: the function must not block after one or more events
  have been handled.
- how do I register a callback to be called when an fh or fd becomes
  "readable" or "writable"?
- how can I register a relative timer?
- are there any limitations, for example, what happens when I register
  two read watchers for one fh (or fd)?
- does stem provide something to catch signals synchronously?
- how about child status changes or exits?

The EV or Event implementation modules should give a good idea of whats
required.

And for the documentation:

- how does stem handle time jumps, if at all?
- are it's timers based on absolute or wallclock time or relative/monotonic 
time?

-- 
                The choice of a       Deliantra, the free code+content MORPG
      -----==-     _GNU_              http://www.deliantra.net
      ----==-- _       generation
      ---==---(_)__  __ ____  __      Marc Lehmann
      --==---/ / _ \/ // /\ \/ /      [EMAIL PROTECTED]
      -=====/_/_//_/\_,_/ /_/\_\

Reply via email to