Résultat inattendu du test de performances node.js vs ASP.NET Core

177

Je fais un test de stress rapide sur deux (un peu) projets Hello World écrits en et . Les deux fonctionnent en mode production et sans enregistreur qui leur est attaché. Le résultat est étonnant! ASP.NET Core surpasse l'application node.js même après avoir effectué un travail supplémentaire, tandis que l'application node.js ne fait que restituer une vue.

Application 1: http://localhost:3000/nodejs node.js

Utilisation : node.js, moteur de rendu express et vash.

application nodejs

Le code de ce point de terminaison est

router.get('/', function(req, res, next) {
  var vm = {
    title: 'Express',
    time: new Date()
  }
  res.render('index', vm);
});

Comme vous pouvez le voir, cela ne fait rien à part l'envoi de la date actuelle via la timevariable à la vue.

App 2: http://localhost:5000/aspnet-core asp.net core

Utilisation : ASP.NET Core, ciblage par modèle par défautdnxcore50

Cependant, cette application fait autre chose que le simple rendu d'une page avec une date. Il génère 5 paragraphes de différents textes aléatoires. Cela devrait théoriquement rendre cela un peu plus lourd que l'application nodejs.

application principale asp.net

Voici la méthode d'action qui rend cette page

[ResponseCache(Location = ResponseCacheLocation.None, NoStore = true)]
[Route("aspnet-core")]
public IActionResult Index()
{
    var sb = new StringBuilder(1024);
    GenerateParagraphs(5, sb);

    ViewData["Message"] = sb.ToString();
    return View();
}

Résultat du test de stress

Résultat du test de résistance de l'application Node.js

Mise à jour: Suite à la suggestion de Gorgi Kosev

En utilisant npm install -g recluster-cli && NODE_ENV=production recluster-cli app.js 8

test nodejs 2

Résultat du test de résistance de l'application ASP.NET Core

résultat du test de résistance de base asp.net

Je ne peux pas en croire mes yeux! Il ne peut pas être vrai que dans ce test de base, asp.net core est bien plus rapide que nodejs. Bien sûr, ce n'est pas la seule métrique utilisée pour mesurer les performances entre ces deux technologies Web, mais je me demande ce que je fais de mal du côté de node.js? .

En tant que développeur professionnel asp.net et souhaitant adapter node.js dans des projets personnels, cela me décourage - car je suis un peu paranoïaque sur la performance. Je pensais que node.js est plus rapide que asp.net core (en général - comme on le voit dans divers autres benchmarks), je veux juste me le prouver (pour m'encourager à adapter node.js).

Veuillez répondre en commentaire si vous souhaitez que j'inclue plus d'extraits de code.

Mise à jour: distribution temporelle de l'application .NET Core

distribution horaire de l'application aspnetcore

Réponse du serveur

HTTP/1.1 200 OK
Cache-Control: no-store,no-cache
Date: Fri, 12 May 2017 07:46:56 GMT
Pragma: no-cache
Transfer-Encoding: chunked
Content-Type: text/html; charset=utf-8
Server: Kestrel
indéfini
la source
52
"J'ai toujours pensé que node.js était plus rapide que le noyau asp.net" - Je suis curieux de savoir pourquoi vous pensez cela? Je n'ai vu aucun benchmark qui soutiendrait cela (les principales raisons que j'ai entendues pour adopter node.js étaient "la facilité d'utilisation" et "un temps de développement / itération plus rapide")
UnholySheep
7
@UnholySheep C'est tout ce que j'ai entendu mon pote, j'ai aussi entendu dire que c'est "facile à utiliser" et "plus rapide à développer" aussi, généralement des personnes qui n'utilisent jamais travaillé dans ASP.NET, en particulier dans VisualStudio. Je ne me vante d'aucune technologie - mais c'est le modèle que j'ai remarqué.
undefined
3
Quelle est la question ici? Si c'est plausible: oui. techempower.com/benchmarks/… .... Mettez également à jour votre toolchain Dnxcore50 est obsolète depuis au moins un an ou deux.
Thomas
2
@Tony utilisant le module de cluster NodeJs engendre plusieurs travailleurs faisant et partageant la charge du processus principal qui écoute sur un seul processus. Cela évite simplement d'avoir à configurer plusieurs applications sur différents ports. De plus, si nodeJs s'exécute en mode cluster, le même nombre d'applications Web Asp.Net devrait s'exécuter dans IIS sur des ports de différence et partager la charge entre eux via un équilibreur de charge, alors ce sera une bonne comparaison.
Vipresh
36
Node.js est idéal pour beaucoup de choses, mais la vitesse brute par requête n'en fait pas partie. Ce dans quoi il excelle, c'est d'être un courtier pour les opérations d'E / S, à cause de la boucle d'événement non bloquante, qui, lorsque Node était nouveau et brillant, était un gros problème. Bien sûr, depuis lors, d'autres langages et frameworks ont rattrapé leur retard, donc dans .NET, nous avons la bibliothèque parallèle de tâches et les E / S asynchrones et async / await. Ce dans quoi Node n'excelle pas, ce sont les opérations liées au processeur telles que le rendu de page, car il s'agit de JavaScript à thread unique.
Mark Rendle

Réponses:

188

Comme beaucoup d'autres l'ont fait allusion, la comparaison manque de contexte.
Au moment de sa sortie, l'approche asynchrone de node.js était révolutionnaire. Depuis lors, d'autres langages et cadres Web ont adopté les approches qu'ils ont adoptées.

Pour comprendre ce que signifie la différence, vous devez simuler une demande de blocage qui représente une charge de travail d'E / S, telle qu'une demande de base de données. Dans un système de thread par demande, cela épuisera le pool de threads et les nouvelles demandes seront placées dans une file d'attente en attente d'un thread disponible.
Avec les frameworks non bloquants, cela ne se produit pas.

Considérez ce serveur node.js qui attend 1 seconde avant de répondre

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

Jetons maintenant 100 connexions simultanées, pendant 10s. Nous nous attendons donc à ce qu'environ 1000 demandes soient traitées.

$ 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

Comme vous pouvez le voir, nous arrivons dans le stade approximatif avec 922 terminés.

Considérons maintenant le code asp.net suivant, écrit comme si async / await n'était pas encore pris en charge, ce qui nous ramène à l'ère du lancement de node.js.

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! Ici, nous voyons la limite du threadpool. En le réglant, nous pourrions obtenir plus de demandes simultanées, mais au prix de plus de ressources serveur.

Pour ces charges de travail liées aux E / S, la décision d'éviter de bloquer les threads de traitement était si dramatique.

Maintenant, apportons-le à aujourd'hui, où cette influence s'est répercutée sur l'industrie et permettons à dotnet de tirer parti de ses améliorations.

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

Pas de surprise ici, nous faisons maintenant correspondre node.js.

Donc qu'est-ce que tout cela veut dire?

Vos impressions que node.js est le "plus rapide" viennent d'une époque dans laquelle nous ne vivons plus. Ajoutez à cela que ce n'était jamais node / js / v8 qui était "rapide", c'était qu'ils ont cassé le thread par requête modèle. Tout le monde a rattrapé son retard.

Si votre objectif est le traitement le plus rapide possible de demandes uniques, examinez les points de repère sérieux au lieu de lancer les vôtres. Mais si à la place ce que vous voulez est simplement quelque chose qui s'adapte aux normes modernes, optez pour le langage que vous aimez et assurez-vous de ne pas bloquer ces threads.

Avertissement: Tout le code écrit et les tests sont exécutés sur un MacBook Air vieillissant pendant un dimanche matin endormi. N'hésitez pas à saisir le code et à l'essayer sur Windows ou à l'adapter à vos besoins - https://github.com/csainty/nodejs-vs-aspnetcore

Chris Sainty
la source
35
NodeJs n'a jamais été unique, le modèle Thread par requête existait également dans Asp.Net avant l'introduction de nodejs. par exemple. methodNameAsync
Vipresh
En tant que par exemple. Vous pouvez vous référer à cet article relatif aux opérations de base de données datant de 2008 codedigest.com/Articles/ADO
...
4
"les approches qu'ils ont adoptées" - peu de choses sont uniques, ils mettent la question devant un public beaucoup plus large. Avoir une approche disponible et l'avoir intégrée comme principe de base sont deux choses très différentes.
Chris Sainty
4
La meilleure réponse ici. Période.
Narvalex
3
@LeeBrindley Je ne suis pas d'accord, cela n'essaie pas de démontrer le débit maximal du matériel donné, cela démontre la différence entre le blocage et le non-blocage. Si vous voulez des comparaisons de débit brut, je lie à techempower.
Chris Sainty
14

Les cadres de nœuds comme Express et Koa ont une surcharge terrible. "Raw" Node est nettement plus rapide.

Je ne l'ai pas essayé, mais il existe un cadre plus récent qui se rapproche beaucoup des performances du nœud "Raw": https://github.com/aerojs/aero

(voir référence sur cette page)

mise à jour: Voici quelques chiffres: https://github.com/blitzprog/webserver-benchmarks

Node:
    31336.78
    31940.29
Aero:
    29922.20
    27738.14
Restify:
    19403.99
    19744.61
Express:
    19020.79
    18937.67
Koa:
    16182.02
    16631.97
Koala:
    5806.04
    6111.47
Hapi:
    497.56
    500.00

Comme vous pouvez le voir, les frais généraux des frameworks node.js les plus populaires sont TRÈS importants!

smorgs
la source
5
à quoi servent les chiffres? Plus haut, mieux c'est?
Iamisti