>> 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) ? Does it work correctly ? 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) { return; } } Or is the "ev_loop()" pictured in your code above refering to the "ev_default_loop()" ? Cheers, Pierre-Yves
_______________________________________________ libev mailing list libev@lists.schmorp.de http://lists.schmorp.de/cgi-bin/mailman/listinfo/libev