This is partly a reaction to people who talk as if Node.js is unique, and partly to test my code against something that has seen production use. There are all sorts of problems with doing this sort of comparison, and while I would have liked to compare more servers, used a better environment, performance tuned everything, done more measurements etc. but I think what I have done is enough to prove my point.So just what is my point? That it is possible (in fact rather easy) to write a high performance event driven server in TCL. I also dislike server-side Javascript and really think the use case for things like Node should be cases where there is a lot of code that can usefully be shared between the client and the server (i.e. you have large chunks of the same code running on both), and not for other, to quote the Node website, “fast, scalable network applications”.

I did some very rough and simple testing. I ran both servers (Node and this) and Apache Bench on my laptop. To ameliorate the effects of running everything locally, used taskset to run the servers being tested on one core, while Apache Bench ran on another. Of course I also shut down anything not needed during testing, and I am aware that by putting both on the same core I am assuming that both would use negligible CPU when not responding to requests (seems reasonable?).

Both servers ran a minimal “Hello World”. I was not familiar with Node but in many ways it was a fairer comparison than I expected: Node is pretty low level, relies on nested callbacks etc. Comparing Node to something like Tornado would be less fair. I used the version of Node that was in the Ubuntu 14.10 repos, so it is not the latest and greatest, but it is likely to be still in production use by many people. Anyway, it is new enough to compare with my code from 2008!

The code for the minimal TCL app:

source dandelion.tcl

proc hello_world {sock headers settings body} {

puts $sock [dict get $::dandelion::first_line 200]

puts $sock “Content-Type: text/plain

”

puts $sock {Hello World!}

close $sock

return

}

::dandelion::init handler hello_world port 8081

vwait forever

The Node code is the HTTP hello world from How to Node.

I ran Apache Bench for 5,000 requests with varying levels of concurrency, (except for 2000 concurrent requests I raised it to 6000 requests). The graphs show results:

The x-axis of the second graph shows the natural log of the number of concurrent connections. The concurrency numbers are the same as in the first graph (1, 10, 100, 500, 1000 and 2000).

Dandelion, my light, embeddable, TCL server has higher performance at low load and performance declines more slowly. The identical performance with no concurrency probably reflects the performance of Apache Bench and the OS more than the servers.

If you think this may not be a consistent result, take a look at a graph of the worst performance from Dandelion against Node’s best:

I am fairly confident that that single point where Dandelion does worse is the result of a data entry error: the worst Dandelion results at that concurrency (1,000) is well below the range of the others (at any concurrency), and within the range of the Node results, and the best of the Node results at that concurrency looks suspiciously high too (not so clear cut because Node results varied more at the same concurrency, and there were better results at lower concurrencies).

So does this prove that everyone should be using TCL? No, Node wins when you need to share code with the front end, and there are event driven servers in many other languages. What it does prove is that there is room for TCL event driven servers, and it has satisfied me that Dandelion can perform well. I do no know how its performance compares to TCLHttpd or Wub, which are undoubtedly more sophisticated, let alone to all the other event driven web app servers around (Twisted, Tornado, Lighttpd (which is scriptable in Lua so could serve as an app server on these lines) etc.

It also may encourage me to dust off the Dandelion code, give it a decent name (I am terrible at coming up with names, so suggestions welcome), and put it in a repo (Fossil for TCL code?). Is there a use case for it (answers welcome)?

I also feel that TCL has missed an opportunity somewhere. Its creator was a proponent of event driven programming. It has had an event driven web and app server for at least 15 years but now, when everyone is using event driven internet servers (not just for the web) it is rarely used and few people even consider it.