web-dev-qa-db-fra.com

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

Je suis en train de faire un test de résistance rapide sur deux (un peu) projets Hello World écrits en node.js et asp.net-core . Les deux fonctionnent en mode de production et sans enregistreur associé. Le résultat est étonnant! Le noyau ASP.NET surpasse l’application node.js même après quelques travaux supplémentaires, alors que l’application node.js ne fait que rendre une vue.

App 1: http://localhost:3000/nodejsnode.js

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

nodejs app

Le code dans ce noeud final est

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

Comme vous pouvez le constater, cela n’a d’importance que d’envoyer à la vue la date du jour via la variable time.

Application 2: http://localhost:5000/aspnet-coreasp.net core

Utilisation de : ASP.NET Core, modèle par défaut ciblant dnxcore50

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

asp.net core app

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

Node.js Résultat du test d'effort de l'application

Mise à jour: suite à la suggestion de Gorgi Kosev

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

nodejs test 2

Résultat du test de contrainte ASP.NET Core App

asp.net core stress test result

Je ne peux pas croire mes yeux! Il n'est pas 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 mesure utilisée pour mesurer les performances entre ces deux technologies Web, mais je me demande qu'est-ce que je fais mal du côté de node.js? .

En tant que développeur asp.net professionnel et souhaitant adapter node.js à des projets personnels, je suis un peu déconcerté, car je suis un peu paranoïaque en matière de performances. Je pensais que node.js est plus rapide que le noyau asp.net (en général, comme le montrent divers autres tests de performance). Je veux simplement me le prouver (pour m'encourager à adapter node.js).

S'il vous plaît répondez en commentaire si vous voulez que j'inclus plus d'extraits de code.

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

aspnetcore app time distribution

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
155
undefined

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

Pour comprendre la différence, vous devez simuler une demande de blocage représentant une charge de travail IO, telle qu'une demande de base de données. Dans un système thread-per-request, 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);
});

Lançons maintenant 100 appels simultanés pendant 10 secondes. Nous attendons donc environ 1000 demandes.

$ 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 constater, nous entrons dans le stade avec 922 complétées.

Considérons maintenant le code asp.net suivant, écrit comme si async/wait n’était pas encore pris en charge, nous permettant donc de remonter à 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! Nous voyons ici la limite du threadpool. En le réglant, nous pourrions obtenir plus de demandes simultanées, mais au prix de davantage de ressources de serveur.

Pour ces charges de travail liées aux E/S, la décision d'éviter le blocage des threads de traitement était aussi spectaculaire.

Passons maintenant à aujourd'hui, où cette influence s'est répercutée sur le secteur et permet à 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 surprises ici, nous correspondons maintenant à node.js.

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

Vos impressions selon lesquelles node.js est le "plus rapide" viennent d'une époque dans laquelle nous ne vivons plus. Ajoutez à cela que ce n'est jamais que le nœud/js/v8 a été "rapide", c'est qu'il a cassé le fil à la requête. modèle. Tous les autres ont rattrapé leur retard.

Si votre objectif est le traitement le plus rapide possible de requêtes uniques, examinez le points de repère sérieux au lieu de lancer le vôtre. Mais si ce que vous voulez est simplement quelque chose qui s'adapte aux normes modernes, optez pour la langue de votre choix et assurez-vous de ne pas bloquer ces fils.

Clause de non-responsabilité: Tous les codes et tests sont exécutés sur un MacBook Air vieillissant pendant une dimanche matin endormie. N'hésitez pas à saisir le code et à l'essayer sous Windows ou à le modifier selon vos besoins - https://github.com/csainty/nodejs-vs-aspnetcore

167
Chris Sainty

Les structures de noeuds comme Express et Koa ont une surcharge terrible. "Raw" Node est nettement plus rapide.

Je ne l'ai pas essayé, mais il existe un nouveau cadre qui se rapproche beaucoup de "Raw" Node performance: https://github.com/aerojs/aero

(voir repère 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 constater, les frais généraux des frameworks node.js les plus populaires sont TRÈS importants!

11
smorgs