So node would probably outperform the given clojure example by 13.5K req/s vs. 8.5k req/s (YMMV).
It is also worth noting that clojure library used (aleph), does not seem to support streaming the response.
The most interesting aspect is clojure's support for futures, and Javascripts lack of such. If you're willing to trade speed for cheap syntactical pleasure, clojure has an advantage here : ).
Clojure should also scale very well on a real 4 core machine (it's the JVM after all). And I wouldn't be surprised if was neck-to-neck with Node.js. Without numbers it's just talk (I don't have access to a real four core machine so I can't say myself).
Also I note that your code is very verbose for managing multiple cores while the Clojure version is pretty much identical to the original Node version.
That's not really a valid test. NodeJS can easily make use of multiple cores with child processes, but by design, it's a very low-level API, so that stuff isn't used by the HTTP server by default. In other words, it doesn't assume you want to use multiple processes for your HTTP server. Maybe you want to use them for something else. (Like, if you have an HTTP server and an IRC server sharing the same box, and you want to make sure they are isolated from one another, or something.)
When leveraging multiple cores, NodeJS is closer to nginx in terms of performance than it is to Jetty or Django. (Of course, nginx uses almost no memory, and NodeJS has this big honkin VM juggling JavaScript contexts, so it's not as space-efficient.)
For stupid web apps that serve content straight from cache, or for servers that are very I/O bound (like anything involving messaging) ... then Node.js may blow Clojure out of the water.
For everything else ... i.e. most startups I see on HN ... you really have to take the CPU-bound or synchronous logic out of Node.js, otherwise it sucks big donkey balls.
People striving for the ultimate development experience have really forgotten what it's like to have brute processing power. Web apps like PlentyOfFish which had 1.2 billion page views/month in 2009 ran only on 2 balanced web servers ... and this considering that on a dating site everything's dynamic, you really can't have too much caching.
Clojure might turn out to be the best of both worlds ... a productive programming language coupled with the brute CPU-bound performance that the JVM can yield.
At first I misread what you said as "NodeJS can easily make use of multiple cores with child processes, by design". It's true, though. Many NodeJS proponents know this. Google Chrome, which uses the same JavaScript engine, V8, works the same way. The fact that it uses lots of lightweight processes is a big selling point of Chrome.
I'm not completely sure about this, but I remember hearing that SpiderMonkey is more suited to using threads, and that's why CouchDB uses it rather than V8.
Multiple processes are an inefficient way of making use of multiple cores. Either you pay memory overhead to duplicate state, or you pay IPC overhead to get access to shared state of some kind.
The main problem both systems have is that they're relatively immature. node.js is still undergoing heavy development, with a few breaking changes every couple of releases (although it's slowing down in that regard). And aleph basically just came out, right?
So I'd regard both as "things to watch" or bootstrapping solutions, not something I'd use for my Global Thermonuclear War management system.
I wrote Aleph this weekend, so yes, it's very new. However, right now it's just a few hundred lines around Netty, which is anything but immature.
I'm certainly not claiming it's flawless, or that there won't be any breaking changes in the future. However, I think this is a great example of one of Clojure's strengths: even brand new projects tend to have solid, well-tested foundations.
I agree. I had a similar problem with CouchDB a while ago when I tried to write the application in CouchDB. The interface was there, but it was obvious that some of the key features hadn't been implemented yet, requiring painful and complex workarounds. I went back to technologies I knew were tried and true.
If you're interested in playing around with tech and having fun, then these technologies are great. But for business I would avoid them for now.
Threads aren't going to scale to the same number of concurrent clients as an evented system though. Isn't that the whole point of things like node? Serving huge numbers of relatively lightweight requests?
If you're doing thread-per-request, than no. If you've got an event-driven I/O system backed by a thread pool for executing parallel requests, than yes.
I set up a Rack adapter through Jetty 7 on JRuby that works exactly like this. The SelectChannelConnector is event-driven I/O, and the QueuedThreadPool handles requests in parallel.
The result? 6k req/sec on my laptop for a simple Rack app, basically the same as what's shown in these examples, since my machine is quite a bit slower, and I've clocked 10k/sec on faster machines.
This looks really nice! Our server is based on Node right now but we've had the idea of porting to Erlang later. Maybe Clojure + Netty is another option to explore.
Node uses Google's V8 virtual machine, which they built for Chrome. JavaScript is single-threaded, so yes, unless you spawn a child process it'll be limited to a single core.
It uses Google's open source V8 JavaScript engine. (http://code.google.com/p/v8/) It doesn't support multiple cores AFAIK. To use multiple cores, the server would need to spawn subprocesses or run multiple servers behind nginx.
I initially had Javascript off, so I figured it was part of the joke when the space for the shortest Node.js web server was empty. When the shortest Clojure web server was also zero characters, I got suspicious.
Don't forget to add a non-Javascript version for people without Javascript (rare) and bots (common).
[+] [-] felixge|15 years ago|reply
http://gist.github.com/430932
So node would probably outperform the given clojure example by 13.5K req/s vs. 8.5k req/s (YMMV).
It is also worth noting that clojure library used (aleph), does not seem to support streaming the response.
The most interesting aspect is clojure's support for futures, and Javascripts lack of such. If you're willing to trade speed for cheap syntactical pleasure, clojure has an advantage here : ).
edit: Who down voted this / why?
[+] [-] swannodette|15 years ago|reply
Also I note that your code is very verbose for managing multiple cores while the Clojure version is pretty much identical to the original Node version.
So much for cheap syntactical pleasures, eh?
[+] [-] IsaacSchlueter|15 years ago|reply
Check out http://github.com/kriszyp/multi-node or http://github.com/extjs/Connect for examples of web servers that will blow Clojure out of the water in this benchmark.
When leveraging multiple cores, NodeJS is closer to nginx in terms of performance than it is to Jetty or Django. (Of course, nginx uses almost no memory, and NodeJS has this big honkin VM juggling JavaScript contexts, so it's not as space-efficient.)
[+] [-] bad_user|15 years ago|reply
For everything else ... i.e. most startups I see on HN ... you really have to take the CPU-bound or synchronous logic out of Node.js, otherwise it sucks big donkey balls.
People striving for the ultimate development experience have really forgotten what it's like to have brute processing power. Web apps like PlentyOfFish which had 1.2 billion page views/month in 2009 ran only on 2 balanced web servers ... and this considering that on a dating site everything's dynamic, you really can't have too much caching.
Clojure might turn out to be the best of both worlds ... a productive programming language coupled with the brute CPU-bound performance that the JVM can yield.
[+] [-] benatkin|15 years ago|reply
I'm not completely sure about this, but I remember hearing that SpiderMonkey is more suited to using threads, and that's why CouchDB uses it rather than V8.
[+] [-] barrkel|15 years ago|reply
[+] [-] mhd|15 years ago|reply
So I'd regard both as "things to watch" or bootstrapping solutions, not something I'd use for my Global Thermonuclear War management system.
[+] [-] prospero|15 years ago|reply
I'm certainly not claiming it's flawless, or that there won't be any breaking changes in the future. However, I think this is a great example of one of Clojure's strengths: even brand new projects tend to have solid, well-tested foundations.
[+] [-] Periodic|15 years ago|reply
If you're interested in playing around with tech and having fun, then these technologies are great. But for business I would avoid them for now.
I'm hoping they gain some traction though.
[+] [-] stratospark|15 years ago|reply
[+] [-] j_baker|15 years ago|reply
[1] http://twistedmatrix.com/trac/
[+] [-] cageface|15 years ago|reply
[+] [-] donw|15 years ago|reply
I set up a Rack adapter through Jetty 7 on JRuby that works exactly like this. The SelectChannelConnector is event-driven I/O, and the QueuedThreadPool handles requests in parallel.
The result? 6k req/sec on my laptop for a simple Rack app, basically the same as what's shown in these examples, since my machine is quite a bit slower, and I've clocked 10k/sec on faster machines.
(By the way, if you're interested, the Rack handler is in a gem called 'mizuno', and is at http://github.com/matadon/mizuno)
[+] [-] nullstyle|15 years ago|reply
At the very least some hackers out there are able to make it scale quite well. Does anyone have a comparable anecdote for Node.js (honest question)?
[+] [-] babo|15 years ago|reply
[+] [-] unknown|15 years ago|reply
[deleted]
[+] [-] jherdman|15 years ago|reply
[+] [-] sjs|15 years ago|reply
[+] [-] ericb|15 years ago|reply
[+] [-] ionfish|15 years ago|reply
[+] [-] srveit|15 years ago|reply
[+] [-] Periodic|15 years ago|reply
Don't forget to add a non-Javascript version for people without Javascript (rare) and bots (common).
[+] [-] c00p3r|15 years ago|reply
Actually, using something like nginx-pr (a-la apache's apr) would be much better solution than this bunch of hacks.
But people never listen. ^_^
[+] [-] kouPhax|15 years ago|reply
[+] [-] francoisdevlin|15 years ago|reply
http://gist.github.com/468107
Code is data :)
[+] [-] twism|15 years ago|reply
[+] [-] stanleydrew|15 years ago|reply
[+] [-] compay|15 years ago|reply