184 votes

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

Je fais un rapide test de stress sur deux (sortes de) projets hello world rédigés en node.js et asp.net-core . Tous deux fonctionnent en mode production et sans enregistreur de données. Le résultat est étonnant ! Le noyau ASP.NET est plus performant que l'application node.js, même après avoir effectué un travail supplémentaire, alors que l'application node.js ne fait que rendre une vue.

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

En utilisant : node.js, moteur de rendu express et vash.

nodejs app

Le code dans ce point final est

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

Comme vous pouvez le voir, il ne fait rien d'autre que d'envoyer la date du jour via le time variable à la vue.

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

En utilisant : ASP.NET Core, ciblage du modèle par défaut dnxcore50

Cependant, cette application fait autre chose que de rendre une page avec une date. Elle génère 5 paragraphes de différents textes aléatoires. Cela devrait théoriquement rendre cette application un peu plus lourde 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 App résultat du test de stress

Mise à jour : Suivant la suggestion de Gorgi Kosev

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

nodejs test 2

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

asp.net core stress test result

Je n'en crois pas mes yeux ! Il ne peut pas être vrai que dans ce test de base, le noyau d'asp.net est bien plus rapide que les noeuds. Bien sûr, ce n'est pas la seule mesure utilisée pour évaluer les performances entre ces deux technologies web, mais je me demande qu'est-ce que je fais de mal du côté de node.js ? .

En tant que développeur professionnel d'asp.net et souhaitant adapter node.js dans des projets personnels, cela me met un peu mal à l'aise - car je suis un peu paranoïaque sur la performance. Je pensais que node.js est plus rapide que le noyau asp.net (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'ajoute d'autres extraits de code.

Mise à jour : Répartition du temps 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

197voto

Chris Sainty Points 5391

Comme beaucoup d'autres y 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 avaient adoptées jusqu'alors.

Pour comprendre la différence, vous devez simuler une demande de blocage qui représente une certaine charge de travail pour les OI, comme une demande de base de données. Dans un système de fil par demande, cela épuisera le pool de fil et les nouvelles demandes seront placées dans une file d'attente en attendant un fil disponible.
Avec des cadres non bloquants, cela ne se produit pas.

Considérons 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 connxions simultanées, pour 10s. Nous attendons donc environ 1000 demandes à traiter.

$ 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 sommes dans la moyenne, avec 922 réalisations.

Considérons maintenant le code asp.net suivant, écrit comme si async/await n'était pas encore supporté, nous remontant donc à l'époque 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 filetage. En l'ajustant, nous pourrions obtenir davantage de requêtes simultanées, mais au prix d'une augmentation des ressources du serveur.

Pour ces charges de travail liées aux OI, la démarche visant à éviter de bloquer les fils de traitement a été aussi spectaculaire.

Venons-en maintenant à la situation actuelle, où cette influence s'est répercutée sur le secteur et a permis à dotnet de tirer profit 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.

Qu'est-ce que tout cela signifie ?

Vos impressions selon lesquelles node.js est le "plus rapide" viennent d'une époque où nous ne vivons plus. Ajoutez à cela que ce n'est jamais les node/js/v8 qui ont été "rapides", c'est qu'ils ont brisé le modèle du fil par demande. Tous les autres ont rattrapé leur retard.

Si votre objectif est le traitement le plus rapide possible des demandes individuelles, consultez la des repères sérieux au lieu de rouler le vôtre. Mais si ce que vous voulez, c'est simplement quelque chose qui s'adapte aux normes modernes, alors optez pour la langue de votre choix et assurez-vous de ne pas bloquer ces fils.

Avertissement : Tout code écrit, et les tests effectués, sur un Macbook Air vieillissant pendant un dimanche matin endormi. N'hésitez pas à récupérer le code et à l'essayer sur Windows ou à le modifier selon vos besoins - https://github.com/csainty/nodejs-vs-aspnetcore

13voto

smorgs Points 419

Les cadres de nœuds comme Express et Koa ont un terrible plafond. Le nœud "brut" est nettement plus rapide.

Je n'ai pas essayé, mais il y a un nouveau cadre qui se rapproche beaucoup de la performance "brute" du nœud : https://github.com/aerojs/aero

(voir le point de 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 dans les cadres les plus populaires de node.js sont TRES importants !

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X