Chris Hawkes Chris Hawkes is a Senior Software Engineer with over 15 years of experience working for Fortune 500 companies. He’s also taught more than 25,000 students on Udemy and nearly 20 million have watched his programming YouTube channel. 10 min read

C# and .NET all the way or NodeJS First?

C# and .NET all the way or NodeJS First?

In this article I'm answering the question from one of my viewers about whether to learn C# or NodeJS first.    My viewer wants to ultimately run a full-stack website to sell cosmetics and beauty supplies.  

What is NodeJS?

As an asynchronous event-driven JavaScript runtime, Node.js is designed to build scalable network applications. In the following "hello world" example, many connections can be handled concurrently. Upon each connection, the callback is fired, but if there is no work to be done, Node.js will sleep.

const http = require('http');

const hostname = '127.0.0.1';
const port = 3000;

const server = http.createServer((req, res) => {
  res.statusCode = 200;
  res.setHeader('Content-Type', 'text/plain');
  res.end('Hello World');
});

server.listen(port, hostname, () => {
  console.log(`Server running at http://${hostname}:${port}/`);
});

What is .NET Core (AKA .NET 5 or just plain C#)?

.NET (previously named .NET Core) is a free and open-source, managed computer software framework for Windows, Linux, and macOS operating systems.  It is a cross-platform successor to .NET Framework. 

Which is faster?

When it comes to speed, NodeJS was once revolutionary and much faster than an ASP.NET Web Forms or MVC.NET application running .NET with C#.   However, as best stated in the benchmarks and explanations mentioned below from Stack Overflow, C# / .NET Core has made vast improvements in speed and is now faster than NodeJS. 

As many others have alluded, the comparison lacks context.
At the time of its release, the async approach of node.js was revolutionary. Since then other languages and web frameworks have been adopting the approaches they took mainstream.

To understand what the difference meant, you need to simulate a blocking request that represents some IO workload, such as a database request. In a thread-per-request system, this will exhaust the threadpool and new requests will be put in to a queue waiting for an available thread.
With non-blocking-io frameworks this does not happen.

Consider this node.js server that waits 1 second before responding

const server = http.createServer((req, res) => {
  setTimeout(() => {
    res.statusCode = 200;
    res.end();
  }, 1000);
});

Now let's throw 100 concurrent connection at it, for 10s. So we expect about 1000 requests to complete.

$ wrk -t100 -c100 -d10s http://localhost:8000
Running 10s test @ http://localhost:8000
  100 threads and 100 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency     1.01s    10.14ms   1.16s    99.57%
    Req/Sec     0.13      0.34     1.00     86.77%
  922 requests in 10.09s, 89.14KB read
Requests/sec:     91.34
Transfer/sec:      8.83KB

As you can see we get in the ballpark with 922 completed.

Now consider the following asp.net code, written as though async/await were not supported yet, therefore dating us back to the node.js launch era.

app.Run((context) =>
{
    Thread.Sleep(1000);
    context.Response.StatusCode = 200;
    return Task.CompletedTask;
});

$ wrk -t100 -c100 -d10s http://localhost:5000
Running 10s test @ http://localhost:5000
  100 threads and 100 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency     1.08s    74.62ms   1.15s   100.00%
    Req/Sec     0.00      0.00     0.00    100.00%
  62 requests in 10.07s, 5.57KB read
  Socket errors: connect 0, read 0, write 0, timeout 54
Requests/sec:      6.16
Transfer/sec:     566.51B

62! Here we see the limit of the threadpool. By tuning it up we could get more concurrent requests happening, but at the cost of more server resources.

For these IO-bound workloads, the move to avoid blocking the processing threads was that dramatic.

Now let's bring it to today, where that influence has rippled through the industry and allow dotnet to take advantage of its improvements.

app.Run(async (context) =>
{
    await Task.Delay(1000);
    context.Response.StatusCode = 200;
});

$ wrk -t100 -c100 -d10s http://localhost:5000
Running 10s test @ http://localhost:5000
  100 threads and 100 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency     1.01s    19.84ms   1.16s    98.26%
    Req/Sec     0.12      0.32     1.00     88.06%
  921 requests in 10.09s, 82.75KB read
Requests/sec:     91.28
Transfer/sec:      8.20KB

No surprises here, we now match node.js.

So what does all this mean?

Your impressions that node.js is the "fastest" come from an era we are no longer living in. Add to that it was never node/js/v8 that were "fast", it was that they broke the thread-per-request model. Everyone else has been catching up.

If your goal is the fastest possible processing of single requests, then look at the serious benchmarks instead of rolling your own. But if instead what you want is simply something that scales to modern standards, then go for whichever language you like and make sure you are not blocking those threads.

Disclaimer: All code written, and tests run, on an aging MacBook Air during a sleepy Sunday morning. Feel free to grab the code and try it on Windows or tweak to your needs - https://github.com/csainty/nodejs-vs-aspnetcore

https://stackoverflow.com/questions/43920942/unexpected-outcome-of-node-js-vs-asp-net-core-performance-test

Here are some more speed tests from TechEmpower.com which also shows .NET core seems to be able to handle more requests than NodeJS. 

Rnk Framework Performance (higher is better) Errors
1 aspcore-mvc-ado-pg 21,230
 
100.0%(46.4%)
0
2 aspcore-mvc-dap-pg 19,051
 
89.7%(41.7%)
0
3 aspcore-mw-ado-my 19,015
 
89.6%(41.6%)
0
4 aspcore-mvc-ado-my 18,425
 
86.8%(40.3%)
0
5 aspcore-mw-ado-pg 18,410
 
86.7%(40.3%)
0
6 aspcore-mw-dap-pg 18,051
 
85.0%(39.5%)
0
7 aspcore-mvc-dap-my 17,262
 
81.3%(37.8%)
0
8 aspcore-mw-dap-my 15,014
 
70.7%(32.8%)
0
9 aspcore-mw-ef-pg 11,755
 
55.4%(25.7%)
0
10 aspcore-mvc-ef-pg 11,746
 
55.3%(25.7%)
0
11 nodejs-mongodb-raw 11,404
 
53.7%(24.9%)
0
12 fastify 9,470
 
44.6%(20.7%)
0
13 nancy-netcore 8,710
 
41.0%(19.1%)
0
14 nodejs 8,522
 
40.1%(18.6%)
0
15 nodejs-mysql 8,453
 
39.8%(18.5%)
0
16 koa 7,930
 
37.4%(17.3%)
0
17 nodejs-chakra 5,692
 
26.8%(12.4%)
0
18 nodejs-postgres 5,551
 
26.1%(12.1%)
0
19 fastify-postgres 5,314
 
25.0%(11.6%)
0
20 koa-postgres 5,305
 
25.0%(11.6%)
0
21 fastify-mysql 4,639
 
21.9%(10.1%)
0
22 express-mysql 4,612
 
21.7%(10.1%)
0
23 koa-mysql 4,508
 
21.2%(9.9%)
0
24 nodejs-mongodb 4,138
 
19.5%(9.1%)
0
25 aspcore-mono-mw-pg 3,633
 
17.1%(7.9%)
0
26 aspcore-mono-pg 3,557
 
16.8%(7.8%)
0
27 aspcore-mono-mvc-pg 3,365
 
15.9%(7.4%)
0
28 express-mongodb 3,244
 
15.3%(7.1%)
0
29 aspcore-mono-mw-my 2,845
 
13.4%(6.2%)
0
30 aspcore-mono-mvc-my 2,408
 
11.3%(5.3%)
0
31 nancy 1,936
 
9.1%(4.2%)
0
32 sailsjs Did not complete
33 sailsjs-postgres Did not complete

https://www.techempower.com/benchmarks/#section=data-r17&hw=ph&test=query&l=gcv6kd-0&p=hweg3v-qt5t8q-d1fif4-72&w=tcd33s-2c8ef-0&f=0-0-jz6vk-0-0-2t4w-0-0-0-0

Should I learn Node.js or ASP.NET C# First?

As much as I want to say that you should learn both, I think it's easier to get started with NodeJS.   There is much less involved in the language syntax compared to C# and .NET.   Also, .NET does way more than just websites.  It's used for video games, software applications, operating systems and more.   NodeJS on the other hand, is simply for building modern websites.    

NodeJS is now used as a modern build tool for much of our front-end web development.   For instance, it's nearly a standard that we have to have NodeJS installed to do just about anything with modern day web development.   C# is only needed when you want to use that as your primary server side stack.   So even if you use C#, you're still going to have to use Node as well to build your front-end (most likely).   

Both are a great choice for websites in 2021.   I think if there is a personal preference to either C# or JavaScript that should probably dictate what you do.   If you couldn't care less, I'd go with NodeJS.