I have always been a big proponent of non-blocking, or asynchronous I/O and longed for more libraries and APIs to support this paradigm to allow implementing scalable applications without relying on massive numbers of threads. For this reason, I am very excited about node.js which fully embraces evented I/O.
I enjoyed this video of the talk entitled node.js: Evented I/O for V8 Javascript (slides) given by its author Ryan Dahl at JSConf.eu on November 8, 2009. (Note that Ryan has been hired by Joyent recently). He describes the major libraries he chose to implement node.js. Most of the qualities of node.js are directly inherited from them:
- v8 (by Google) is of course the javascript engine and is the main pillar of node.js.
- libev (by Marc Lehmann) is an event loop similar to the well-known libevent. According to its author, libev outperforms libevent in multiple benchmarks. It is even able to emulate the libevent API.
- libeio (by Marc Lehmann) is a fantastic idea: it relies on POSIX threads to provide an asynchronous version of the POSIX API: open, close, stat, unlink, fdatasync, mknod, etc. It would be nice if UNIX kernels provided this asynchronism natively, because the overhead of using a thread for a stat() call when the inode data is already cached in memory is significant.
- c-ares (by Daniel Stenberg) provides an asynchronous DNS resolver. node.js versions before 0.1.90 used udns instead. Another popular asynchronous DNS resolver is adns.
- evcom (by Ryan Dahl) is a stream socket library on top of libev.
- http-parser (by Ryan Dahl) has nothing to do with non-blocking I/O but it seems to be a cool little lib to keep on one's mind when dealing with HTTP.
According to Ryan Dahl, other good non-blocking I/O libraries include:
- EventMachine for Ruby, C++, and Java.
- Twisted for Python.
- AnyEvent for Perl.
He gave more recent talks at two other JSConf events, of which I cannot find videos, but here are the slides:
- node.js, JSConf.us, April 17, 2010.
- 9 challenges in node.js, JSConf.eu, September 26, 2010.
I should conclude this post by saying that non-blocking I/O by itself is not the perfect solution to scaling. Neither is threading. The best solution an a multi-processor machine is one process per physical (thread) processor which each process running an event loop doing non-blocking I/O. This allows for maximum usage of CPU resources while using the minimum number of processes possible to reduce context switching overhead. According to its homepage, node.js will soon allow this kind of application by using the Web Workers API... I am looking forward to it.