Resultado inesperado de node.js vs ASP.NET Core prueba de rendimiento

177

Estoy haciendo una prueba de esfuerzo rápida en dos (un poco) proyectos de hello world escritos en y . Ambos se ejecutan en modo de producción y sin un registrador conectado a ellos. ¡El resultado es asombroso! El núcleo de ASP.NET está superando a la aplicación node.js incluso después de hacer un trabajo adicional, mientras que la aplicación node.js solo muestra una vista.

Aplicación 1: http://localhost:3000/nodejs node.js

Usando : node.js, motor de renderizado express y vash.

aplicación nodejs

El código en este punto final es

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

Como puede ver, no hace nada más que enviar la fecha actual a través de la timevariable a la vista.

Aplicación 2: http://localhost:5000/aspnet-core asp.net core

Uso : ASP.NET Core, orientación de plantilla predeterminadadnxcore50

Sin embargo, esta aplicación hace algo más que simplemente representar una página con una fecha. Genera 5 párrafos de varios textos aleatorios. En teoría, esto debería hacer que esto sea un poco más pesado que la aplicación nodejs.

aplicación asp.net core

Aquí está el método de acción que representa esta página.

[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();
}

Resultado de la prueba de esfuerzo

Resultado de la prueba de esfuerzo de la aplicación Node.js

Actualización: siguiendo la sugerencia de Gorgi Kosev

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

prueba de nodejs 2

Resultado de la prueba de esfuerzo de la aplicación ASP.NET Core

resultado de la prueba de esfuerzo de asp.net core

No puedo creer lo que veo! No puede ser cierto que en esta prueba básica asp.net core sea mucho más rápido que nodejs. Por supuesto, esta no es la única métrica utilizada para medir el rendimiento entre estas dos tecnologías web, pero me pregunto qué estoy haciendo mal en el lado de node.js. .

Siendo un desarrollador profesional de asp.net y deseando adaptar node.js en proyectos personales, esto es algo que me desanima, ya que estoy un poco paranoico sobre el rendimiento. Pensé que node.js es más rápido que asp.net core (en general, como se ve en varios otros puntos de referencia). Solo quiero probarlo por mí mismo (animarme a adaptar node.js).

Responda en un comentario si desea que incluya más fragmentos de código.

Actualización: distribución de tiempo de la aplicación .NET Core

distribución de tiempo de la aplicación aspnetcore

Respuesta del servidor

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
indefinido
fuente
52
"Siempre pensé que node.js es más rápido que asp.net core" . Tengo curiosidad por qué piensas eso. No he visto ningún punto de referencia que lo respalde (las principales razones que escuché para adoptar node.js fueron "facilidad de uso" y "tiempo de desarrollo / iteración más rápido")
UnholySheep
77
@UnholySheep Es todo lo que escuché, compañero, también escuché que es "fácil de usar" y "más rápido de desarrollar", por lo general, el uso de personas nunca funcionó en ASP.NET, especialmente en VisualStudio. No me estoy jactando de ninguna tecnología, pero este es el patrón que noté.
indefinido
3
¿Cuál es la pregunta aquí? Si es plausible: Sí lo es. techempower.com/benchmarks/… .... También actualice su cadena de herramientas Dnxcore50 está desactualizado por al menos uno o dos años.
Thomas
2
@Tony utilizando el módulo de clúster NodeJs genera múltiples trabajadores y comparte la carga del proceso principal que está escuchando en un solo proceso. Simplemente evita tener que configurar múltiples aplicaciones en diferentes puertos. Además, si nodeJs se ejecuta en modo de clúster, entonces debería haber la misma cantidad de aplicaciones web Asp.Net que se ejecutan en IIS en puertos diff y compartir la carga entre ellas a través de algún equilibrador de carga, entonces será la comparación correcta.
Vipresh
36
Node.js es ideal para muchas cosas, pero la velocidad bruta por solicitud no es una de ellas. En lo que se destaca es en ser un intermediario para las operaciones de E / S, debido al evento de bucle de eventos sin bloqueo, que, cuando Node era nuevo y brillante, era un gran problema. Por supuesto, desde entonces, otros lenguajes y marcos se han puesto al día, por lo que en .NET tenemos la Biblioteca de tareas paralelas y E / S asíncrona y async / wait. En lo que Node no sobresale es en las operaciones vinculadas a la CPU, como la representación de páginas, porque es JavaScript de un solo subproceso.
Mark Rendle

Respuestas:

188

Como muchos otros han aludido, la comparación carece de contexto.
En el momento de su lanzamiento, el enfoque asíncrono de node.js era revolucionario. Desde entonces, otros lenguajes y marcos web han estado adoptando los enfoques que adoptaron en la corriente principal.

Para comprender el significado de la diferencia, debe simular una solicitud de bloqueo que represente alguna carga de trabajo de E / S, como una solicitud de base de datos. En un sistema de subprocesos por solicitud, esto agotará el conjunto de subprocesos y las nuevas solicitudes se colocarán en una cola en espera de un subproceso disponible.
Con los frameworks sin bloqueo de io esto no sucede.

Considere este servidor node.js que espera 1 segundo antes de responder

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

Ahora arrojemos 100 conexiones concurrentes, durante 10 segundos. Por lo tanto, esperamos completar unas 1000 solicitudes.

$ 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

Como puede ver, llegamos al estadio con 922 completados.

Ahora considere el siguiente código asp.net, escrito como si async / await aún no fuera compatible, por lo tanto, nos remonta a la era de lanzamiento 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! Aquí vemos el límite del conjunto de hilos. Al ajustarlo, podríamos obtener más solicitudes concurrentes, pero a costa de más recursos del servidor.

Para estas cargas de trabajo vinculadas a IO, el movimiento para evitar bloquear los hilos de procesamiento fue tan dramático.

Ahora traigámoslo a la actualidad, donde esa influencia se ha extendido por la industria y permite que dotnet aproveche sus mejoras.

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 hay sorpresas aquí, ahora coincidimos con node.js.

Entonces, ¿qué significa todo esto?

Sus impresiones de que node.js es el "más rápido" provienen de una era en la que ya no vivimos. Agregue que nunca fue node / js / v8 lo que fue "rápido", fue que rompieron el hilo por solicitud modelo. Todos los demás han estado poniéndose al día.

Si su objetivo es el procesamiento más rápido posible de solicitudes individuales, mire los puntos de referencia serios en lugar de lanzar los suyos. Pero si, en cambio, lo que quiere es simplemente algo que se ajuste a los estándares modernos, busque el idioma que desee y asegúrese de no bloquear esos hilos.

Descargo de responsabilidad: todo el código escrito y las pruebas se ejecutan en un MacBook Air antiguo durante un sueño el domingo por la mañana. Siéntase libre de tomar el código y probarlo en Windows o ajustarlo a sus necesidades: https://github.com/csainty/nodejs-vs-aspnetcore

Chris Sainty
fuente
35
NodeJs nunca fue único, el modelo de subprocesos por solicitud también existía en Asp.Net antes de que se introdujera nodejs. Todos los métodos que hicieron E / S tenían 2 versiones síncronas y asíncronas proporcionadas por Framework, sus métodos ASYNC terminaban con la palabra clave "Async" para p.ej. methodNameAsync
Vipresh
Como un eg. U puede consultar este artículo relacionado con las operaciones de DB que datan de 2008 codedigest.com/Articles/ADO/…
Vipresh
44
"los enfoques que tomaron en la corriente principal": pocas cosas son únicas, ponen el tema frente a una audiencia mucho más amplia. Tener un enfoque disponible y tenerlo como principio básico son dos cosas muy diferentes.
Chris Sainty
44
La mejor respuesta aquí. Período.
Narvalex
3
@LeeBrindley No estoy de acuerdo, esto no está tratando de demostrar el rendimiento máximo del hardware dado, está demostrando la diferencia entre bloqueo y no bloqueo. Si desea comparaciones de rendimiento sin procesar, lo enlazo a techempower.
Chris Sainty
14

Los marcos de nodo como Express y Koa tienen una sobrecarga terrible. El nodo "crudo" es significativamente más rápido.

No lo he probado, pero hay un marco más nuevo que se acerca mucho al rendimiento del nodo "sin procesar": https://github.com/aerojs/aero

(ver punto de referencia en esa página)

actualización: Aquí hay algunas cifras: 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

Como puede ver, ¡los gastos generales en los frameworks node.js más populares son MUY significativos!

smorgs
fuente
55
¿Para qué son los números? ¿Cuanto más alto mejor?
Iamisti