.NET and Node.JS – Performance Comparison (Updated)

Update (3/31/2013 – 11:41 PM PST): This article has been updated! As most readers have commented the node.js async package is not asynchronous, which is what the original article was based on. I made an assumption I should not have. I have since rerun the tests taking this into account, as well as some of the changes recommended by Guillaume Lecomte. I have decided to update this existing post so that there’s no confusion in the future with the data. Thank you everyone for all the comments, posts and keeping me sane.

Update (3/29/2013 – 3:43 PM PST): There’s been a lot of valid comments around the use of the async NPM package for node.js which are valid. I will take them into account and re-run these tests.

If you talk to any silicon valley startup today chances are you will hear about node.js. One of the key reasons most argue is that node.js is fast, scalable because of forced non-blocking IO, and it’s efficient use of a single threaded model. I personally love JavaScript, so being able to use JavaScript on the server side seemed like a key gain. But I was never really sold into the notion that node.js is supremely fast because there aren’t any context switches and thread synchronizations. We all know these practices should be avoided at all costs in any multi-threaded program, but to give it all away seemed like an extreme. But if that meant consistently higher performance, then sure, that would make sense. So I wanted to test this theory. I wanted to find out exactly how fast node.js was compared to .NET – as empirically as possible.

So I wanted to come up with a problem that involved IO (ideally not involving a database), and some computation. And I wanted to do this under load, so that I could see how each system behaves under pressure. I came up with the following problem: I have approximately 200 files, each containing somewhere between 10 to 30 thousand random decimals. Each request to the server would contain a number such as: /1 or /120, the service would then open the corresponding file, read the contents, and sort them in memory and output the median value. That’s it. Our goal is to reach a maximum of 200 simultaneous requests, so the idea is that each request would have a corresponding file without ever overlapping.

I also wanted to align the two platforms (.NET and Node.js). For instance, I didn’t want to host the .NET service on IIS because it seemed unfair to pay the cost of all the things IIS comes with (caching, routing, performance counters), only to never use them. I also avoided the entire ASP.NET pipeline, including MVC for the same reasons, they all come with features, which we don’t care about in this case.

Okay, so both .NET and Node.JS will create a basic HTTP listener. What about client? The plan here is to create a simple .NET console app that drives load to the service. While the client is written in .NET, the key point here is that we test both .NET and Node.JS services using the same client. So at a minimum how the client is written is a negligible problem. Before we delve into the details, let’s look the graph that shows us the results:

.NET and Node.JS - Performance Comparison

Performance of sorting numbers between .NET and Node.JS

On an average Node.js wins hands down. Even though there are few spikes that could be attributed to various disk related anomalies, as some of the readers have eluded to. I also want to clarify that if you look at the graph carefully you start to see that the two lines start to intersect towards the end of the test run, while that might start to give you the impression that overtime the performance for .NET and node.js converge the reality is .NET starts to suffer even more over time. Let’s look at each aspect of this test more carefully.

We’ll start with the client, the client uses a HttpClient to drive requests to the service. The response times are maintained on the client side so that there aren’t any drastic implementation difference on the service that could impact our numbers. Notice that I avoided doing any Console.Write (which blocks) until the very end.

public void Start()
{
    Task[] tasks = new Task[this.tasks];

    for (int i = 0; i < this.tasks; ++i)
    {
        tasks[i] = this.Perform(i);
    }

    Task.WaitAll(tasks);

    result.ToList().ForEach(Console.WriteLine);
}
public async Task Perform(int state)
{
    string url = String.Format("{0}{1}", this.baseUrl, state.ToString().PadLeft(3, '0'));
    var client = new HttpClient();
    Stopwatch timer = new Stopwatch();

    timer.Start();
    string result = await client.GetStringAsync(url);
    timer.Stop();

    this.result.Enqueue(String.Format("{0,4}\t{1,5}\t{2}", url, timer.ElapsedMilliseconds, result));
}

With that client, we can start looking at the service. First we’ll start with the node.js implementation. One of the beauties of node.js is it’s succinct syntax. With less than 40 lines of code we are able to fork processes based on the number of CPU cores and share the CPU-bound tasks amongst them.

var http = require('http');
var fs = require('fs');
var cluster = require('cluster');
var numCPUs = require('os').cpus().length;

if (cluster.isMaster) {
    // Fork workers.
    for (var i = 0; i < numCPUs; i++) {
        cluster.fork();
    }

    cluster.on('exit', function(worker, code, signal) {
        console.log('worker ' + worker.process.pid + ' died');
    });
} 
else {
	http.createServer(function(request, response) {
		var file = parseInt(request.url.substring(1));
		file = file % 200;
		file = String("000" + file).slice(-3);

		// read the file
		fs.readFile('../data/input'+file+'.txt', 'ascii', function(err, data) {
			if(err) {
				response.writeHead(400, {'Content-Type':'text/plain'});
				response.end();
			}
			else {
				var results = data.toString().split("\r\n");

				results.sort();
				response.writeHead(200, {'Content-Type': 'text/plain'});
				response.end('input'+file+'.txt\t' + results[(parseInt(results.length/2))]);
			}
		});
	}).listen(8080, '127.0.0.1');
}
console.log('Server running at http://127.0.0.1:8080/')

And lastly, let’s look at the .NET service implementation. Needless to say we are using .NET 4.5, with all the glories of async/await. As I mentioned earlier, I wanted to compare purely .NET without IIS or ASP.NET, so I started off with a simple HTTP listener:

public async Task Start()
{
    while (true)
    {
        var context = await this.listener.GetContextAsync();
        this.ProcessRequest(context);
    }
}

With that I am able to start processing each request, as requests come in I read the file stream asynchronously so I am not blocking my Threadpool thread, and perform the in-memory sort which is a simple Task that wraps the Array.Sort. With .NET I could have severely improved performance in this area by using parallel sorting algorithms which come right of the parallel extensions, but I choose not to because that really isn’t the point of this test.

private async void ProcessRequest(HttpListenerContext context)
{
    try
    {
        var filename = this.GetFileFromUrl(context.Request.Url.PathAndQuery.Substring(1));
        string rawData = string.Empty;

        using (StreamReader reader = new StreamReader(Path.Combine(dataDirectory, filename)))
        {
            rawData = await reader.ReadToEndAsync();
        }
        
        var sorted = await this.SortAsync(context, rawData);
        var response = encoding.GetBytes(String.Format("{0}\t{1}", filename, sorted[sorted.Length / 2]));

        await context.Response.OutputStream.WriteAsync(response, 0, response.Length);
        context.Response.StatusCode = (int)HttpStatusCode.OK;
    }
    catch(Exception e) 
    {
        context.Response.StatusCode = (int)HttpStatusCode.BadRequest;
        Console.WriteLine(e.Message);
    }
    finally
    {
        context.Response.Close();
    }
}

private async Task<string[]> SortAsync(HttpListenerContext context, string rawData)
{
    return await Task.Factory.StartNew(() =>
    {
        var array = rawData.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries);
        Array.Sort(array);

        return array;
    });
}

You can download the entire source code, this zip file includes both client, and service sources for both .NET and node.js. It also includes a tool to generate the random number files, so that you can run the tests on your local machine. You will also find the raw numbers in the zip file.

I hope this was useful to you all as you’re deciding to choose the next framework to build your services on. For most startups the key pivot point is performance, scalability over anything else and node.js clearly shines as we’ve shown today.

Also, please remember some of the comments below are based on the original article which was using the async NPM package. This article has since been updated with the corrected information.

64 Comments .NET and Node.JS – Performance Comparison (Updated)

  1. Matt

    async.sortBy is for sorting the results of an array of asynchronous functions. It is not an asynchronous sort. Let’s see how it fares with process.nextTick(function(){array.sort()}) (or better still, threads-a-gogo).

    Reply
  2. asdf

    .NET has such a highly organized and cohesive framework that there’s nothing else that comes close.

    Java?

    Reply
        1. kayes

          I came into .Net from java and found it nicely organised and cohesive, it was so easy to fit in, ONLY BECAUSE it ‘copied’ java’s organisation and cohesiveness :)

          Reply
          1. Govind

            C# didn’t copy from java actually java and C# both copied from C++.

            C# language design is better than java, I work on both but i found C# have better design. (better generics, delegation, and )

  3. Castig

    Great article! I thought you had to use .NET with IIS. Is it possible to use it without? Also… don’t most people use IIS, and therefore shouldn’t that be considered as a common use case.

    Reply
    1. bbqchickenrobot

      Yes, you can run asp.net or regular .net applications on Mac OS X and Linux variants using mono. Checkout Xamarin Studio (MonoDevelop) for writing code in a cool IDE that’s cross platform.

      You can host asp.net apps using apache/mod_mono, nginx, xsp (not recommended but possible), Kayak, Manos de Mono and Katana.

      Reply
  4. Viktor

    Test not seem to be fair. How many Node.JS instances were used? Since 1 instance uses 1 core and actually is not a multi-threading process, you need to utilize as many Node.JS instances as many cores you’d like to utilize.

    Reply
  5. Masklinn

    I think you’ve completely misunderstood what async.sortBy does, considering your implementation of SortAsync: Node’s equivalent to SortAsync would roughly be process.nextTick(function(){array.sort()}), possibly sparked into a threadpool for added concurrency: a single short of synchronous sorting lifted out of the main request.

    Meanwhile the purpose of async.sortBy is to sort by an asynchronous key function (the library’s example is sorting file names by their mtime, requiring an async call to stat() to get the info), the equivalent .Net function would need to take (and use) an asynchronous IComparer and use that for its sorting.

    Reply
  6. Meryn Stol

    It’s obvious that you’re new to Node.js.

    First of all, you should be aware that Async.js is a mere flow-control library. It does not offload work to separate threads, and neither is it able to parallelize work. Internally, it mostly does bean-counting (but very helpfully so).

    As you can see in the source https://github.com/caolan/async/blob/master/lib/async.js#L359 async.sortBy simply uses Array.sort for the actual sorting. The only reason you’d want to use Async.sortBy is if the values that the array of “keys” is not known beforehand (and needed to be loaded through io – asynchronously). This is clearly exemplified in the documentation. https://github.com/caolan/async#sortBy

    The implication of this that your call to async.sortby can be replaced by a call to array.sort. This will remove two unnecessary runs of async.map, inflicting a potentially huge performance penalty.

    You do need to pass array.sort a comparator function, otherwise it will sort lexicographically (see https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/sort ). That said, I’m not sure what the actual contents of your input file is. In your .Net example, you do not seem to bother to convert the array of strings to an array of ints (or floats). I think that .Net sort will sort an array of strings lexicographically as well. Furthermore, in the node.js example, you seem to be content with returning the resulting median as an int, not as float. Do the input “decimals” in the input file represent ints or floats? Do they all have exactly the same amount of decimals? Are both the Node.js and .Net algorithms doing the same thing? I think not.

    Finally, we get to Array.sort. Array.sort blocks. Depending on the multi-threading efficiency of the underlying algorithm of Array.sort (which I don’t have insight in), the code may not be able to use all available system resources. Keep in mind that Node.js is single-threaded. I practically don’t know anything about .Net, but I assume it will magically start new processes and or threads if the runtime deems this beneficial. For Node.js, you may want to try the Cluster api, http://nodejs.org/api/cluster.html . You could try seeing if performance increases by adding one or more extra server processes.

    I can’t comment about the quality of the .net code since I don’t have any experience with it.

    I think it would be fair (and very educative to others) if you’d rerun the benchmarks with
    1. Async.sortBy replaced with array.sort
    2. with both .Net and Node.js algorithms fully doing the same thing (i.e. let them both sort either floats, ints, or strings), and
    3. at least one extra server process for Node.
    I think most interesting would be if you’d made the changes step-by-step, and run the benchmarks at each step.

    My guess is that step 1 would give the biggest difference.
    Depending on how you decide to resolve the differences in the two algorithms, performance of your .Net code may be slightly affected. It could potentially be speed up in fact, if somehow it’s able to sort ints (or floats) faster than strings. The actual job of sorting probably overshadows it all though.

    Reply
  7. alex

    What you do here is to compare apples with oranges, read what masklinn says on HN:


    It’s a benchmark of .Net’s Array.Sort to NPM’s third-party async.sortBy, not a benchmark of .Net to Node, and the test does not make sense: async.sortBy is used to sort an array on an asynchronous function, it does not perform an asynchronous sort (which is what the asynchronized Array.Sort does)

    Reply
  8. Nathan Alden, Sr.

    Imagine that! An enterprise-class framework (.NET) is faster than Node.js (a boutique framework created just because someone could). Who woulda thunk it? Even if Node.js performed better, you couldn’t get me to switch. C# and .NET together are much, much too powerful a combination. With .NET I know that my application’s code will scale with my business.

    Reply
    1. Bo Aphran

      You can never know that your application will scale with your business, from which language or even framework you choose. It depends on your code.

      Reply
  9. Justin Koreska

    Yes!

    Strong typing, all-powerful IDE, vast ecosystem, and performance! .NET FTW!

    Seriously, I’ve been building toy projects and trying hard to justify the use of Node.js or other OSS async web frameworks the last 6 months but I think I’ve been spoiled by C# and .NET! Dropping EF and going with RavenDB and async and NServiceBus and SignalR makes for a mean backend with super clean code that’s fast and scalable.

    Thanks for your work and reinforcing my growing love for C# and .NET!

    Reply
    1. JPKab

      You do realize we are talking about one tool vs. another, right?

      Because by reading your comment, I feel like I may have misread the article, and that it in fact discusses the second coming of Jesus.

      In which case, I agree. Jesus and heaven FTW!!!

      Reply
  10. Alexander

    Hi! It seems like you’ve compared custom JavaScript sorting of floats with build-in sorting of strings in .NET. Didn’t you know that V8 is a single-threaded VM and async sorting wouldn’t provide any benefit?

    Reply
  11. Dan MacTough

    Two problems:

    1. Using async.sortBy is pointless and probably slowing things down. You’re not doing a sort on the results of a bunch of async operations. That’s what you would use async for; it doesn’t magically make sorting asynchronous. Node has non-blocking asynchronous I/O. Sorting is not I/O. Just use native JS sort.

    2. If you’re going to read a file from the filesystem on every request, then you’re really just benchmarking the filesystem performance. You don’t say if both .NET and Node are running on the same machine, but assuming they are, it would be a Windows platform. So you’re basically benchmarking .NET’s filesystem performance, which is probably optimized for Windows, versus Node’s, which is not. In any event, a benchmark that forces filesystem I/O on each request is silly. You would never configure a server that way if you want it to be fast, so why run a benchmark against that configuration.

    Reply
  12. Ingo Rammer

    I was just wondering if this might not just be more of a comparison of “a random third party algorithm” vs a .NET standard algorithm. Given the somewhat contrived example of using an async sort algorithm in a non-parallel scenario (with node), it might actually also just be a microbenchmark of tail call optimization between V8 and the CLR.

    Reply
  13. JDavis

    What a horrible article.

    But then again I shouldn’t have expected anything better from a .net benchmark from a Microsoft employee..

    Async.js is an idiotic choice of sorting algos. I won’t even bother to list all the other problems here. Next time learn to program.

    Reply
  14. Tony

    Is the node async sort blocking? I could be misunderstanding the code for it but it doesn’t look like it can do a sort that is non-blocking. If this is true then the test, to me, is void.

    I don’t mind which is “faster” but I just want to make sure we are comparing apples to apples or at least as close as possible. Can anyone confirm or deny this?

    If the sort is non-blocking, can someone explain how this is possible in JS/Node as it is single threaded?

    Thanks,
    Tony

    Reply
  15. Alexey

    Great comparison! While I admire javascript, I don’t think it stands a chance on the server side. Not yet.

    Reply
  16. Drew Marsh

    In both cases it makes no sense to push the array sorting off of the current thread. It’s a completely compute bound operation and by pushing the work to another thread you’re just paying the over head of some kind of context switching for no reason. Change that for both and re-run the tests and you’ll have something much more useful/realistic.

    Reply
  17. eddyb

    I should point out that the library you’re using could be solely responsible for the difference in speed.

    I took a look at its source, it has abstracted array methods that at the lowest level are based on a “parallel” forEach.
    “Seemingly non-blocking” would be a better name than “parallel”, because they’re using process.nextTick as a scheduler (which could be costly).

    Now I’ve heard they’ve made some changes in nextTick for 0.10, but you haven’t mentioned the Node.js version.

    Reply
  18. mark

    Kind of pointless. .NET and JVM are static. Thing is nodeJS is FAST enough and libraries can be shared between the server and the web (you know that space where MS is getting killed in). Try running .NET on a 128MB VPS. Ooops.

    Reply
  19. Stilgar

    I don’t know much about Node.js but sorting numbers in memory is a CPU bound operation so in my opinion it makes no sense to use async sorting algorithm. It seems to me that you allowed .NET to use multiple cores by making a new Task for sorting while denying this to Node since Node is single threaded.

    Reply
  20. Gabe Ghearing

    Funny, that the Node.js code is over 1000 lines where the .Net code is under 100.

    While I’m no .Net developer I’m guessing this isn’t performant C# for reading number from a text file(which is the only thing tested in this benchmark)

    var array = input.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries).ToList();
    array.Sort();

    Reply
  21. Mark Kahn

    Assuming you’re using a quad-core CPU which .Net has access to and node.js doesn’t (with this code), and that based on your chart .Net is scaling approx 2.7x faster than node, processor correction puts node at actually running about 150% as fast as .Net per core.

    If you were ran this on a 8-core machine, node is running about 3x as fast as .Net

    Please bother to understand what you’re benchmarking

    Reply
  22. Andrius Bentkus

    This article is flawed.
    It compared .NET to Node.js? Really?

    You can compare the languages, their features, but when it comes down to the base class libraries – it just doesn’t make any sense. Node.js is a JavaScript engine(v8) + IO library(libuv). That IO library is called libuv and I have created bindings for C#: http://github.com/txdv/LibuvSharp
    Now if you use the same underlying library on both runtimes, the performance check should be more relevant.

    The writer of the article tests file read performance, libuv is not very fast in this area, because the operating system does not support file IO in the way that libuv uses it. libuv tries to use a central event loop, kqueue on bsd, epoll on linux, IOCP on Windows. Epoll and kqueue operate very fast on network IO, but use a simple thread pool for file IO.

    So if you try to measure the file IO performance, you are already on .NETs side, because the BCL supports the blocking API on an OS level, while node.js approach is not supported on an OS level, only emulated. The performance check should be more relevant if only network IO would be involved.

    The article is basically saying a porsche is better then a tractor, because it is faster, a comparison so irrelevant that it gives me headaches.

    reddit comment: http://www.reddit.com/r/programming/comments/1b8lds/net_and_nodejs_performance_comparison/c94o6z5?context=3

    Reply
  23. Jay K.

    Given the responses, I can’t wait to see the horde of rebuttal blog posts on the horizon.

    As for me, I use both, though not for web development, and I like them both. I guess I’m Swiss. :)

    Reply
  24. Brad C

    I don’t think you have a strong grasp of nodejs.

    You should be running node on linux, and you need to make sure it’s setup for multi-process if it’s on a multi-core machine. Also, as many others have stated, your “sort by” construction is very wrong.

    Also, I think .NET should probably win this test anyway. If most of the “load” is in-memory computation, then a statically compiled language is going to be faster than a dynamic one.

    Cheers!

    Reply
  25. Trevor Norris

    Just posted this in a response blog. Take these into account:

    There is one huge problem. It reads a file from disk. Disk I/O is one of the most unpredictable performance indicators when used in other high performance scenarios that require high throughput. IMHO I’d pre-cache the files in memory on startup, then check the throughput.

    First it would be helpful to try this out in the latest v0.11 release. Which has upgrade v8 and now uses the new WriteOneByte API, instead of the old WriteAscii. This offers a 30% performance increase for writing js strings into external memory.

    For a slightly deeper analysis, it’s pretty obvious where all the performance is going (other than disk I/O). First you’re reading a string from external memory into the v8 heap. Then the split and sort. Then writing it back out to an external buffer. Since we’re allowing the use of modules, it’d be semi-trivial to create a string split-n-sort in cc, create a js api and then operate on it directly.

    Finally there are a few little things that are v8 specific. For example, parseInt sucks. Instead replace that with “(results.length – (results.length % 2)) / 2)”. This will force the value to remain an Smi, and not overflow to a Double.

    Reply
    1. Greg

      I can pretty much guarantee the disk IO is right near 0. The file-system will have cached the file on the first request if it hadn’t already been cached from writing it or having it open in the editor.

      Reply
  26. ReignMain

    I have no dog in this race, I use what I enjoy which is neither and don’t believe in premature performance optimization (which is how I view these meaningless tests), but I wouldn’t concede the performance crown to Node.JS based on 1 test. Sorry.

    Reply
    1. Salman Quazi

      I agree with you .NET is a great ecosystem – in fact it’s probably one of the most cohesive framework in existence today. But this was just purely a IO/compute comparison because I was curious.

      Reply
  27. Stilgar

    Nope. Still not right. The async sort in C# is as pointless as it is in Node. Of course you should ensure that the HttpListener can handle simultaneous requests based on the number of CPU cores. I assume this is what Node.js will do when you fork the process.

    Reply
  28. Pingback: Renae

  29. donjoe

    “few spikes that could be attributed to various disk related anomalies, as some of the readers have eluded to”

    That would be “… alluded to”.

    Reply
  30. csharpdev

    Funny how you added async whereever you could in the C#-Code. I got it running at same speed with using Begin/EndGetContext without any async keywords.
    I don’t know if it speeds it up much, but did you benchmark the release build?

    Reply
  31. honeymonster

    There are still serious problems with (at least) your C# implementation:

    1) Your “custom” .NET http server is single threaded! Your code will only ever listen on requests on a single thread, whereas your node.js implementations immediately forks out a number of listeners.

    Even if you “await” .NET does not spin up another thread. Basically you are capping the performance and only allowing your custom service to start listening for new requests once it has handed of the work to another thread.

    2) Which leads us to the next problem: Your C# ProcessRequest method *also* reads the file single threaded, that is ON THE THREAD used for dispatching. Yes, you do “await” but that will only land you back in Start which will then start waiting. You really should do that on the task you spin up for sorting instead of on the request thread.

    3) You use “async void” – which is very much adviced against: http://msdn.microsoft.com/en-us/magazine/jj991977.aspx

    You should read this for how to set up multi threaded http listener: http://stackoverflow.com/questions/4672010/multi-threading-with-net-httplistener

    Reply
  32. Sergey

    C# code becomes about 2 times faster if you change sorting from strings to doubles, so that sorting function would look like this:
    private async Task SortAsync(HttpListenerContext context, string rawData)
    {
    return await Task.Factory.StartNew(() =>
    {
    var array = (from n in rawData.Split(new string[] { “\r\n” }, StringSplitOptions.RemoveEmptyEntries)
    select double.Parse(n)).ToArray();
    Array.Sort(array);

    return array;
    });
    }

    but how do you sort array as doubles, instead of strings?
    results.sort(function(a,b){return a-b;});
    and results.sort(function(a,b){return
    parseFloat(a)-parseFloat(b);});

    produce incorrect results, so I’m a bit stuck here, but I’m still curious how node.js works with double comparison

    Reply
  33. Jon Okie

    I see 4 things that I don’t believe represent an apples to apples comparison between the Node.js and .Net code.

    Number one, in the Node.js code, you are specifying the file encoding when opening the file. On the .Net side, by not specifying the Encoding, you are telling StreamReader to try to detect it. How many CPU cycles are used doing this? I don’t know, but it’s not apples to apples.

    Number two, why are you doing an asynchronous sort in .Net but not Node.js. It may be that the cost of starting a new thread to sort a small amount of data is not worth it. I want to see the .Net code without the async sort.

    Third, you are doing a concatenation of the response content in Node.js while using String.Format in the .Net code. String.Format needs to parse out the “{x}” variables first and then do a concatenation. In my tests, I show doing a simple concatenation of a small number of strings takes less than half the amount of time vs using String.Format.

    Finally, you have try-catch-finally blocks around the code in .Net. This changes the code and adds a number of statements for doing error handling and cleanup. I want to see try-catch-finally statements added to the Node.js code too.

    Reply
  34. Jon Okie

    I see 4 things that I don’t believe represent an apples-to-apples comparison between the Node.js and .Net code.

    Number one, in the Node.js code, you are specifying the file encoding when opening the file. On the .Net side, by not specifying the Encoding, you are telling StreamReader to try to detect it. How many CPU cycles are used doing this? I don’t know, but it’s not apples to apples.

    Number two, why are you doing an asynchronous sort in .Net but not Node.js. It may be that the cost of starting a new thread to sort a small amount of data is not worth it. I want to see the .Net code without the async sort.

    Third, you are doing a concatenation of the response content in Node.js while using String.Format in the .Net code. String.Format needs to parse out the “{x}” variables first and then do a concatenation. In my tests, I show doing a simple concatenation of a small number of strings takes less than half the amount of time vs using String.Format.

    Finally, you have try-catch-finally blocks around the code in .Net. This changes the code and adds a number of statements for doing error handling and cleanup. I want to see try-catch-finally statements added to the Node.js code too.

    Reply
  35. Dan Harman

    Why would you not use a parallel sort in the .net implementation, or are you purely trying to benchmark request handling?

    If the latter not sure why you would involve file IO and a sort implementation.

    What is interesting is that node is performant, way faster than I had expected, which is great to know.

    Reply
  36. Ken

    Nice comparison.

    Many words were written here on optimizing the node implementation. I’ll write a bit about the .NET side:

    1. Similar to the argument about node’s “async” sorting of the array, on the .NET sample, wrapping the Array.Sort call in a Task and awaiting on it is totally unnecessary, and should be removed. Just split the rawData and .Sort it.

    2. Furthermore, the .NET server implementation is using a single httpListener. while the node one is spanning a listener per core. Somewhat unfair … you should be running multiple httpListeners (per number of cores) to make the comparison more fair.
    There also might be machine level configurations regarding max connections etc., that on a desktop windows OS are not necessarily optimal for highly concurrent servers (or load-testing harnesses for that matter).

    To make things easier on the server side, I’d advise you take a look at Katana. Use its OwinHost to run a Katana app that is similar to the node app, and then measure.

    Reply
  37. ee

    while (true)
    {
    var context = await this.listener.GetContextAsync();
    this.ProcessRequest(context);
    }
    await in while also block the loop,it run in one thread

    Reply
  38. ee

    while (true)
    {
    var context = await this.listener.GetContextAsync();
    this.ProcessRequest(context);
    }
    ProcessRequest not async , await in while block the loop ,it not run in parallel, pleace use begin/end mode.

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *


× five = 25

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>