I've implemented the "addListener" observer pattern for most of Node.
I think it looks good and has cleaned up a lot of the internal
interfaces. I wanted to see how it compared to the original simple
callbacks.
To do this I ran a simple web server which when you go to /bytes/123,
it returns 123 bytes of data. When you go to /bytes/24576 it returns
24kb of data. The code for this web server is in the repository.
I tested the new code "node (events)" against the old code "node
(callbacks)". For comparison I threw in the results of two Ruby
language web servers, "ebb" and "thin".
I ran two runs with apache bench on all 4 servers: once with 123 byte
responses and once with 24 kb responses. Each run was done with 30
concurrent clients (-c 30) for 60 seconds (-t 60). I recorded the data
to a csv file with -g and made the graphs with R. (See
http://four.livejournal.com/955976.html?thread=2677320#t2677320 for
the script I used.)
Results:
123 bytes, histogram:
http://s3.amazonaws.com/four.livejournal/20090627/small_hist.png
123 bytes, time series (note, ab stops after 50,000 requests, that's
why it doesn't last for the full 60 seconds)
http://s3.amazonaws.com/four.livejournal/20090627/small_ts.png
24kb, histogram
http://s3.amazonaws.com/four.livejournal/20090627/big_hist.png
24kb, timeseries
http://s3.amazonaws.com/four.livejournal/20090627/big_ts.png
raw data:
http://s3.amazonaws.com/four.livejournal/20090627/stats.tar.bz2
Conclusion:
There is a definite performance hit using more complex event
interface. This is most observable in the 123 byte benchmark. This
makes sense since events are being triggered more rapidly. Looking at
larger responses, however, the difference is nearly negligible.