Hacker News new | ask | show | jobs
by j_baker 5812 days ago
The examples given seem to indicate that evented servers are as fast or faster than threaded servers. If that's the case, why doesn't everyone just use evented servers?
5 comments

First, the analysis relies on every step from request to response being evented, which in turn relies on the existence of event-based libraries for everything you want to do.

Also, most languages don't have a good way of dealing with callbacks. They tend to make the code verbose and difficult to reason about. This is especially true for non-trivial applications, where there are more than two or three callbacks chained together.

However, you can counter-argue that the additional complexity isn't endemic to the programming model, only certain languages. Also, in languages which support multiple threads (read: not Javascript), a hybrid approach that uses events where possible, and threads where necessary, may retain many of the benefits of the event-based approach.

First, the analysis relies on every step from request to response being evented, which in turn relies on the existence of event-based libraries for everything you want to do.

This is one of the main reasons I like node.js, EVERYTHING is evented, if it isn't it's probably a bug, or at least carefully explained why it can't be (and usually there's an async alternative).

IIRC it does not support things like the mysql lib because it is normally not event driven. So yes everything in node.js is event driven, but not everything you may need is included. Last I checked work was being done on it. The solution was to create a thread pool and treat communicating with it as an event driven protocol.
I think the answer is actually pretty straightforward. It's trivial to go from a serial to a threaded server. It's way harder to write an event-based server using poll or select.

Serially:

  int handle_connection(int fd) {
    ...
  }

  int loop() {
    ...
    while(1) {
      fd = accept(listener);
      handle_connection(fd);
    }
  }
Threaded:

  int handle_connection(int fd) {
    ...
  }

  int loop() {
    ...
    while(1) {
      fd = accept(listener);
      thread_start(handle_connection, fd);
    }
  }
No its not. Using your contrived limited example its even less code.

Evented:

  int handle_connection(int fd) {
    ...
  }

  int doaccept() {
      put_on_event_loop(accept(listener));
  }
IMNSHO (dealing with both kinds in some cases):

Probably because they weren't popular. And they weren't popular because they were hard to write in "classic" languages. I'd never try to write a complex asynchronous server in a language like C, or Java. But then, I'd never try to write a thread-per-connection server in Python. Limiting ourselves to popular languages only: "old" ones didn't provide good support for this kind of thing. In "new" ones evented servers are trivial with closures, simulated continuations, etc. This might seem silly, but look at the slides 36 from "Paul Tyma" mentioned in another comment. "Found that when switching between clients, the code for saving and restoring values/state was difficult" - I'm not even sure what he means by that... why save / restore? That seems like a seriously difficult way to write the code.

Then again there are places where you really shouldn't choose one over another, unless you've got a really good reason. For example in telecommunication when you're dealing with signalling, doing thread per connection is close to insane. That's one of the reasons there's only a handful of people who understand chan_sip in the Asterisk project and why it's full of DEADLOCK_AVOIDANCE macros.

This Usenix article argues that threaded servers are a better programming model, though it admits that evented servers with current setups may be more efficient (e.g. if there's no compiler support for minimizing per-thread stack overhead): http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.5.58...
Reply to myself since it's been too long to edit: Decided this was maybe worth its own submission -> http://news.ycombinator.com/item?id=1547353
A lot of existing libraries, web services and other external resources make eventing more difficult since they don't provide an asynchronous way of using them.

In the case of node.js for example a lot of libraries (mysql for example) have to be wrapped or rewritten since it would block the whole event loop.