ev_async_send() not trigerring corresponding async handler in target loop ?

Denis F. Latypoff denis at gostats.ru
Tue Dec 29 16:41:59 CET 2009


Hello Pierre-Yves,

Tuesday, December 29, 2009, 9:37:16 PM, you wrote:

>>> Your experience is interesting, but I have a question: why do you need
>>> threads in event-driven machine? I just tested my app based on libev,
>>> it works as followed:
>>> 
>>> bind();
>>> listen();
>>> 
>>> for (i = 0; i < 4; ++i)
>>> {
>>>   switch (fork())
>>>   {
>>>   case -1: /* epic fail */ break;
>>>   case  0: return run_loop();
>>>   default: /* manage worker (ev_child_init, ev_child_start etc) */
>>>   }
>>>   /*
>>>    * Watch workers
>>>    */
>>>   ev_loop();
>>> }
>>> 
>>> int run_loop(void)
>>> {
>>>   /*
>>>    * Ignore all signals as master process will manage them itself.
>>>    * Do accept() which is managed by kernel instead of master
>>>    * process.
>>>    */
>>>   ev_loop();
>>> }
>>> 
>>> With this model I get about 17k req/s (including HTTP/1.0 protocol
>>> parsing) on 4 CPU server.
>> 
>> These threads are "worker threads", and there are several of them because a single threaded program would
>> only use one core on a multi-way server. In your example above, you replaced thread by processes (which is
>> barely the same on Linux for instance).
>> 
>> Also, the small HTTP server stub was just an example of code to pinpoint concurrency problems, understand
>> where the fds were being lost and get an estimation of performance (and most importantly use "ab"). My worker
>> threads will in fact perform much more operations at each request, including memory structure manipulation
>> and disk I/O (which may block a little). Threading (or forking) is then necessary to avoid one particular client
>> processing to stuck the entire clients stack.

> Ooops, just realized something else in your email: you're actually
> forking _after_ bind()/listen() (which is fine) and
> all child processes are adding the listening socket to their own
> event loop (in an ev_io handler I guess) ?

Surprise!

> Does it work correctly ?

Yup :))

> I mean I'm pretty sure that when a connection is
> presented to the listening socket, all processes wake-up
> but only one accept() succeed and the others fail with negative
> status (this situation is probably handled in your code
> right) ? In other terms, your accept_cb() is probably like this:

> void accept_cb()
> {
>     if (accept(...) < 0)
>     {
          /*
           * This isn't meaning that another worker already accepted
           * new connection.
           */
>         return;
>     }
> }

> Or is the "ev_loop()" pictured in your code above refering to the "ev_default_loop()" ?

Yes.

> Cheers,
> Pierre-Yves


-- 
Best regards,
 Denis                            mailto:denis at gostats.ru




More information about the libev mailing list