Node.js vs .Net performance

David Merrilees picture David Merrilees · Feb 15, 2012 · Viewed 112.6k times · Source

I've read a lot about Node.js being fast and able to accommodate large amounts of load. Does anyone have any real-world evidence of this vs other frameworks, particularly .Net? Most of the articles I've read are anecdotal or don't have comparisons to .Net.

Answer

Matt Dotson picture Matt Dotson · Jun 16, 2012

Being FAST and handling lots of LOAD are two different things. A server that's really FAST at serving one request per second might totally croak if you send it 500 requests per second (under LOAD).

You also have to consider static (and cached) vs dynamic pages. If you're worried about static pages, then IIS is probably going to beat node because IIS uses kernel-mode caching, which means that requests which request a static page are not even going to get out of the kernel.

I'm guessing that you're looking for a comparison between ASP.NET and node. In this battle, after everything's been compiled/interpreted you're probably going to be pretty close in performance. Maybe .NET's a little FASTER or maybe node's a little FASTER, but it's probably close enough that you don't care. I'd bet on .NET, but I don't know for sure.

The place that node is really compelling is for handling LOAD. This is where the technologies really differ. ASP.NET dedicates a thread for each request from its thread pool, and once ASP.NET has exhausted all the available threads requests begin to get queued up. If you're serving "Hello World" apps like the example by @shankar, then this might not matter that much because the threads aren't going to be blocked and you're going to be able to handle a lot of requests before you run out of threads. The problem with the ASP.NET model comes when you start making I/O requests that block the thread (call to a DB, make an http request to a service, read a file from disk). These blocking requests mean that your valuable thread from the thread pool is doing nothing. The more blocking you have, the less LOAD your ASP.NET app is going to be able to serve.

To prevent this blocking, you use I/O completion ports which don't require holding a thread while you wait for a response. ASP.NET supports this, but unfortunately many of the common frameworks/libraries in .NET DON'T. For example, ADO.NET supports I/O completion ports, but Entity Framework doesn't use them. So you can build an ASP.NET app that's purely asynchronous and handles lots of load, but most people don't because it isn't as easy as building one that's synchronous, and you might not be able to use some of your favorite parts of the framework (like linq to entities) if you do.

The problem is that ASP.NET (and the .NET Framework) were created to be un-opinionated about asynchronous I/O. .NET doesn't care if you write synchronous or asynchronous code, so it's up to the developer to make this decision. Part of this is because threading and programming with asynchronous operations was thought to be "hard", and .NET wanted to make everyone happy (noobs and experts). It got even harder because .NET ended up with 3-4 different patterns for doing async. .NET 4.5 is trying to go back and retrofit the .NET framework to have an opinionated model around async IO, but it may be a while until the frameworks you care about actually support it.

The designers of node on the other hand, made an opinionated choice that ALL I/O should be async. Because of this decision, node designers were also able to make the decision that each instance of node would be single threaded to minimize thread switching, and that one thread would just execute code that had been queued. That might be a new request, it might be the callback from a DB request, it might be the callback from a http rest request you made. Node tries to maximize CPU efficiency by eliminating thread context switches. Because node made this opinionated choice that ALL I/O is asynchronous, that also means that all it's frameworks/add-ons support this choice. It's easier to write apps that are 100% async in node (because node forces you to write apps that are async).

Again, I don't have any hard numbers to prove one way or another, but I think node would win the LOAD competition for the typical web app. A highly optimized (100% async) .NET app might give the equivalent node.js app a run for it's money, but if you took an average of all the .NET and all the node apps out there, on average node probably handles more LOAD.

Hope that helps.