SimonHF's Blog

Just another site

node.js versus Lua “Hello World” — Postmortem October 23, 2010

Filed under: Uncategorized — simonhf @ 4:54 pm
Tags: , , , , , , ,

Last time I performance tested an experimental version of the soon to be released SXELua against node.js. What I found is that SXELua is 2.9 times faster with the simple “Hello World” test. However, what I didn’t mention is why SXELua is so much faster. When first running the test with a very early version of SXELua then the results were about half as good as the node.js+net+crcr results! The reason for this is the way that Lua handles its strings. During the simple “Hello World” test then HTTP queries are read using the following code path: libev C code calls SXE C code which read()s the HTTP query string and then passes the string to the Lua read event handler. During this last step then Lua ‘internalizes’ the string. This means that Lua does a quick hash (alert: more expensive operation) over the string, allocates memory for it, and copies it… and later unfortunately garbage collects it too. All these operations take lots of CPU. The simple “Hello World” benchmark sends 500,000 HTTP query strings which are each 199 bytes. So you can imagine how even heavily optimized string internalization code might get bogged down with such a large number of strings to internalize and eventually garbage collect. In-fact, take any small overhead and multiply it by 500,000 and suddenly it becomes a large overhead. So in the end Neil change SXELua so that Lua’s string handling code isn’t used and instead Lua calls back out to SXE C code to do all its string handling. This works very fast because C is very fast, and calling C from Lua or vice-versa is very fast, and SXE itself uses neither malloc() nor dynamic memory garbage collection techniques while processing queries. So this means that SXELua is limited to only using an if… then… call subset of syntax of Lua? Yes! And if you think about it then this makes perfect sense. Why? Because it’s faster to do the generic ‘heavy lifting’ — for example, string — operations in C than it is in Lua… especially if this avoids internalization and garbage collection. The part that I’d like to rapidly code in Lua is the lighter-weight, non-generic, business logic of the program. In the end this works out really well and SXELua is 2.9 times faster than the node.js simple “Hello World” test. This is probably mainly because node.js has three different types of overhead in this particular test: 1. JavaScript string manipulation code is slower than C string manipulation code and this difference gets multiplied 500,000 times. 2. JavaScript creates 500,000 strings. 3. JavaScript garbage collects 500,000 strings. So it’s easy to see why both the SXELua and SXE simple “Hello World” tests are 2.9 times and 3.4 times faster than the node.js equivalent.


node.js versus Lua “Hello World” October 13, 2010

Neil Watkiss — known among other things for many cool Perl modules — has created a non-optimized, experimental version of SXE (pronounced ‘sexy’) containing embedded Lua called SXELua. So I thought it would be fun to redo the familiar – to readers of this blog – ‘Hello World’ benchmark using SXELua. And here is the Lua source code:

    local connect = function (sxe) end
    local read = function (sxe, content)
        if content:match("\r\n\r\n", -4) then sxe_write(sxe,"HTTP/1.0 200 OK\r\nConnection: Close\r\nContent-Type: text/html\r\nContent-Length: 14\r\n\r\nHello World\n\r\n")
    local close = function (sxe) end
    sxe_register(10001, function () sxe_listen(sxe_new_tcp("", 8000, connect, read, close)) end)

Compare this with the slightly longer node.js equivalent from the last blog:

var net = require('net');
var server = net.createServer(function (stream) {
  stream.on('connect', function () {});
  stream.on('data', function (data) {
    var l = data.length;
    if (l >= 4 && data[l - 4] == 0xd && data [l - 3] == 0xa && data[l - 2] == 0xd && data[l - 1] == 0xa) {
      stream.write('HTTP/1.0 200 OK\r\nConnection: Keep-Alive\r\nContent-Type: text/html\r\nContent-Length: 13\r\n\r\nHello World\r\n');
  stream.on('end', function () {stream.end();});
server.listen(8000, 'localhost');

And now the updated results:

“Hello World”    Queries/ % Speed
Server           Second   of SXE
---------------- -------- -------
node.js+http     12,344    16%
Node.js+net+crcr 23,224    30% <-- *1
Node.js+net      28,867    37%
SXELua           66,731    85%
SXE              78,437   100%

In conclusion, calling Lua functions from C and vice-versa is very fast… close  to the speed of C itself. I am very excited by how well Lua performed in the benchmark. The Lua “Hello World” program performed 3.6 times better than the node.js equivalent. After a quick Google it looks like this isn’t the first time that JavaScript V8 has gone up against Lua; these results suggest that SXELua could get even faster after optimization. It looks like Lua will become part of SXE soon. Lua seems ideal for creating tests for SXE & SXELua programs alike, and prototyping programs. Stay tuned…!

*1 Update: Somebody who knows JavaScript better than me offered faster code to detect the “\n\r\n\r”. I updated the script above and the resulting queries per second and % speed of SXE.


%d bloggers like this: