By using a Java JDBC database driver you're completely losing any async support. Same presumably goes for redis or Mongo drivers. You can do some of the work with threads and pooling, but it's still not the same, and makes this another useless micro benchmark.
You don't actually get a performance boost from Node being "async". Node's async abilities simply give you transparent access to threads that are otherwise unavailable with javascript, and it's the threads giving you performance.
The async API is actually a price to pay (spaghettification).
For example, the go language took a different approach: it created a cheap thread-like construct which doesn't incur in the biggest overhead of classical threading (namely pre-allocated linear stacks and context switching/sleeping requiring a systemcall; all this aided by the compiler), and a cheap mean of communication (channels).
Then, the whole core IO library was written using a multiplexing async model (epoll...), which communicates with the user part of the library via channels). The result is a blocking like API which under the hood behaves like an async implementation.
A similar goal is also met by http://www.neilmix.com/narrativejs/doc/ and other javascript 'weavers' which convert "sequantial looking" code into callbacks.
It's been found that if you employ only a single thread (that can run any number of tasks) you get a performance boost over using a larger threadpool under some conditions, but a single thread wouldn't let you scale by taking advantage of all processors.
Yes, that's exactly Node's main selling proposition everybody forgets when presenting their next Node.js
Other platforms/languages have real concurrency constructs and don't suffer node's limitations.
I don't know whether making JS single-threaded was a principled decision -- if anything it was presumably the KISS principle at work. However, it was actually a ridiculously nice choice to offer a single-threaded-asynchrony model. It sometimes gets in the way rather obtusely -- Firefox can still (if very rarely) fail to introspect and then crash when some ad script on your page goes into an infinite loop! -- but on the whole, it is very nice to always know that while I'm in this function, modifying this variable, nobody else can interfere.
With that said, I also think that the lack of good concurrency planning is indeed missing, and that it will probably enter the language at a future time.
At best it's "making a virtue out of necessity".
You say that like it's a good thing. I'd much rather have the choice between async and sync.
Sure programming-wise it's nice to have sync. No argument there.
Sounds like you're quoting from the "Node.js Is Bad Ass Rock Star Tech" satire video ( http://www.youtube.com/watch?v=bzkRVzciAZg ).
Nothing inherently special about "forcing the entire ecosystem to be async too", especially since Node is more or less FORCED to do that, because javascript is single threaded.
Add the bad callback spaghetti implementation of async, and the main benefit of Node is easy deployment, and accessibility to the millions of javascript programmers.
As an async environment it doesn't offer anything either new or too compelling.
That isn't strictly true.
If you focus on the traditional scripting languages as your competition: Ruby, Python, PHP, Perl: Then you start to realise that Node.js does offer a similar language structure (dynamic, no compilation, etc), with the benefits of thousands of concurrent connections (which those languages will do with certain modules) but while forcing all the libraries to also be async (which those languages DO NOT do).
At my last job I had to build an SMTP server capable of scaling to 50k concurrent connections. Building this in Perl was fine, except for any library I wanted to use - all of the libraries were synchronous. So now I wrote Haraka, which Craigslist are now using as their incoming SMTP server.
If you compare all that to Java you get slightly less performance but probably lower memory requirements. And that's OK. Different strokes for different folks.
The jvm has amazing threading support, doubly so if you use it with a language like scala or clojure. You can and should handle the connections asynchronously and use a thread pool for things like db access. It works well, people have done this with the jvm for years.
It has both event loops and a background thread pool, so you can choose which to run your task on depending on what kind of thing it is.
E.g. it's stupid to run long running or blocking actions on an event loop.