Wishful Coding

Didn't you ever wish your
computer understood you?

JS server benchmark: Node.js & Rhino

Background

I’m playing with the idea of writing a little web framework in JavaScript using jQuery on both the server and the browser. To run jQuery on the server, you need — except for JavaScript — some magic, such as env.js and jsdom.

Env.js is a complete browser environment that allows you to run almost all browser JS code(like jQuery) on Rhino, a JavaScript engine written in Java. It is very complete, but tied to Rhino.

Jsdom is a younger project implementing only the DOM in CommonJS, though it is written for Node.js, an event-based network server based en Googles V8 JavaScript engine.

While I know some Java, and env.js does all I need, I got the impression that Node.js offers more in terms of speed and is more suitable for a web framework.

Since jsdom does not do AJAX and events, I’m facing the choice between using Rhino, or porting env.js to Node. I started to investigate the possibilities, and here is what I found.

Running the benchmark

Searching for benchmarks comparing server side JavaScript, I found none. I did find the JS benchmark Google uses to test V8, which might of course be skewed towards V8. I tried them anyway.

Node.js

Installing Node was a breeze, but getting the V8 benchmark to run on a V8 based framework was not so easy.

For some unknown reason the V8 benchmark uses load() to load everything together, while Node uses require(), with a slightly different meaning, which made simply substituting them impossible.

Stride on #node.js came up with the solution, consisting of concatenating the files together with some shell magic:

cat base.js crypto.js deltablue.js earley-boyer.js raytrace.js regexp.js richards.js splay.js run.js > v8bench.js

Note that the order of the files was important, otherwise a simple “cat *.js” would have sufficed.

Now all that remained was commenting out the original imports and defining a print function:

print = require('sys').log

Now this is the result:

$ node v8bench.js
19 Aug 16:13:25 - Crypto: 2434
19 Aug 16:13:26 - DeltaBlue: 3150
19 Aug 16:13:28 - EarleyBoyer: 12752
19 Aug 16:13:29 - RayTrace: 6230
19 Aug 16:13:30 - RegExp: 2287
19 Aug 16:13:31 - Richards: 1547
19 Aug 16:13:33 - Splay: 8879
19 Aug 16:13:33 - ----
19 Aug 16:13:33 - Score (version 5): 4090

Note the last number(average score) and the length of the command(2 parts).

Rhino

Installing Rhino was equally easy(just “port install rhino nodejs”)

Then the trouble started… First I had to figure out how to run Rhino, because it doesn’t come with its own command, like Node does. Turns out it’s “java -jar /path/to/js.jar”

After that, I ran ‘run.js’ from the v8 benchmark, and it just worked! Without modification! … Until it gave java.lang.OutOfMemoryError. Some Googling reveals that unless you have a memory leak in your app, you can increase the memory limit, which I did.

Here are the results for Rhino:

$ java -Xmx265m -jar js.jar run.js
Richards: 20.4
DeltaBlue: 138
Crypto: 120
RayTrace: 253
EarleyBoyer: 248
RegExp: 59.1
Splay: 279
----
Score (version 5): 120

Again note the score and the length of the command(5 parts). The -Xmx265m is for raising the memory limit.

My verdict

Sure, Node’s score is about 34 times the score of Rhino, but I talked to the author of Claypool, and he used Rhino for several production sites, without performance problems. It’s a measurement without a scale, so I can’t judge if it will matter to me.

With the speed sorted out, there is just the general style and comfort of both systems. Node.js is a very young C++ project, while Rhino has been around since the Netscape ages and is written in Java.

While I’m attracted to the speed and freshness of Node, I know more Java than I know C++, and there are tons of Java libs available to Rhino. And then there is env.js, which needs to be ported to Node, if I decide to use that.

Besides the porting and library issue, there is also hosting. Because Node is so new, you’d have to rent your own VPS, while Rhino can run in any Java servlet container, and even Google App Engine with the help of Rhino-for-webapps

So, my verdict? Undecided: As always, it depends on what you want, and I’m not yet sure what I want.

[update]

FireFox gets only 394 in the same test, so Rhino is probably not that bad.

I would be very grateful if anyone could give me some information on the CommonJS load/require and print problem or ways to speed up Rhino.