Scalable Network Programming
scribd.com
scribd.com
However I do not expect to reach 600 million queries per month, at least not in the first month ;)
Memcached is one example of a purely event driven application. Another example (also by Brad Fitzpatrick) is perlbal (written in Perl and using epoll).
1 process per connection (bad) -> 1 thread per connection (better?) -> 1 process (bingo!)
For HTTP servers hosting static content, you may be able to out-perform the OS thread scheduler. For most non-trivial apps, you're probably wrong.
Small fork()-ed processes can still compete with clever poll(), /dev/epoll, or kqueue()-based servers, if you can keep each instance lightweight.
Why wouldn't you be able to virtually always do a better job of scheduling events (when you control all the code competing for resources) than a generic OS scheduler?
> Small fork()-ed processes can still compete with clever poll(), /dev/epoll, or kqueue()-based servers, if you can keep each instance lightweight.
Do you know of any examples of ultra highly scalable fork()ing servers?
Simply put, I would say that "you" (where "you" is an average webapp developer) probably don't understand scheduling, event-driven programming, or memory management as well as the average kernel developer. I of course don't mean this to extend to anyone in this thread. Imagine, though, giving your average PHP or ASP developer, who may struggle to implement a basic sort algorithm, the problem of implementing cooperative multitasking in a scalable way.
> Do you know of any examples of ultra highly scalable fork()ing servers?
Under real-world workloads, I still consider Apache to be "highly scalable." In my experience, given 1:1 investment in hardware for front-end and database servers, the RDBMS craps out long before the webapp, so being able to accept another 5000 incoming connections is only going to hurt you.
Why is it false? As the other reply notes, you have more domain knowledge than the kernel's scheduler does. You also didn't need to pay the overhead of entering the kernel to context switch (which is why context switches between userspace threads are cheaper than between kernel threads). In the case of fork()-based servers, you also need to flush the TLB (depending on the CPU architecture).
I'd be curious to see links that support your last claim: AFAIK, it is fairly well-known that event-based daemons using epoll/kqueue are the most performant technique for writing scalable network servers. See C10K, etc.
I'm not challenging the fact that the C10K architecture wins if we're talking about static content. Real webapps don't live and die by their static content performance, though: the critical path is through the dynamic content generation, which means that select()/poll()/et. al. don't buy you much, unless you can hook your database client events and application thread scheduling inside that loop as well.
Green (a.k.a. userspace) threads are one good solution, but fork() isn't the performance-killer that people seem to think it is, either.
Personally, I like having my orthogonal processes running in isolation from each other, mediated through a tested, scalable kernel.
Obviously, there's a balance to be found between needless context switches and dangerous coupling of function, but I've found that, as often as not, a process context per user is actually a pretty good point to come down on within that continuum.
If you have 5000 concurrent sessions in a single OS-level process, you better have some pretty damn good fault-recovery mechanisms built into that process.
When you get right down to it, this is the same basic argument gets used to support Erlang: namely, that it supports large number of cooperating, isolated processes, rather than shoving everything into a single monolithic server.
I trust that the Linux (or BSD, Solaris, or other reasonable OS) kernel can handle scheduling a few thousand processes smoothly, so long as those processes fit into available RAM.
What kills big Apache (or other fork()-driven) server environments isn't context switching between backends, it's swapping.
That being said, you're right about it being all about scale. If you're like Google, or Facebook, and can afford to hire engineers who do nothing but worry about scaling to 10K sessions on each HTTP host by moving your critical-path code into hand-tuned C++ or Java inside the polling server, more power to you. If you're in the normal world most of us live in, where scalability via hardware is more economical than via developer time, then fault isolation may prove more useful than raw throughput.
After all, the actual networking code isn't cpu heavy.
That way you don't have to deal with any synchronization or concurrency issues in the networking code at all.
Incidentally, the justin.tv chat server uses one thread per cpu, and epoll for its network io, and currently scales to a little over 10,000 connections per cpu (see http://irc.justin.tv/ for other numbers). It's the most scalable irc server that I'm aware of. I keep meaning to write something up about it...