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:[email protected]
_______________________________________________
libev mailing list
[email protected]
http://lists.schmorp.de/cgi-bin/mailman/listinfo/libev