asp - node js vs.net core
Node.js vs.Net rendimiento (5)
Hice una prueba de rendimiento rudimentaria entre nodejs e IIS. IIS es aproximadamente 2,5 veces más rápido que nodejs cuando se reparte "¡Hola, mundo!". código a continuación.
mi hardware: Dell Latitude E6510, Core i5 (doble núcleo), 8 GB de RAM, Windows 7 Enterprise SO de 64 bits
servidor de nodos
runs at http://localhost:9090/
/// <reference path="node-vsdoc.js" />
var http = require("http");
http.createServer(function (request, response) {
response.writeHead(200, { "Content-Type": "text/html" });
response.write("<p>hello, world!</p>");
response.end();
}).listen(9090);
default.htm
hosted by iis at http://localhost/test/
<p>hello, world!</p>
mi propio programa de referencia que usa la biblioteca paralela de tareas:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
using System.Diagnostics;
namespace HttpBench
{
class Program
{
private int TotalCount = 100000;
private int ConcurrentThreads = 1000;
private int failedCount;
private int totalBytes;
private int totalTime;
private int completedCount;
private static object lockObj = new object();
/// <summary>
/// main entry point
/// </summary>
static void Main(string[] args)
{
Program p = new Program();
p.Run(args);
}
/// <summary>
/// actual execution
/// </summary>
private void Run(string[] args)
{
// check command line
if (args.Length == 0)
{
this.PrintUsage();
return;
}
if (args[0] == "/?" || args[0] == "/h")
{
this.PrintUsage();
return;
}
// use parallel library, download data
ParallelOptions options = new ParallelOptions();
options.MaxDegreeOfParallelism = this.ConcurrentThreads;
int start = Environment.TickCount;
Parallel.For(0, this.TotalCount, options, i =>
{
this.DownloadUrl(i, args[0]);
}
);
int end = Environment.TickCount;
// print results
this.Print("Total requests sent: {0}", true, this.TotalCount);
this.Print("Concurrent threads: {0}", true, this.ConcurrentThreads);
this.Print("Total completed requests: {0}", true, this.completedCount);
this.Print("Failed requests: {0}", true, this.failedCount);
this.Print("Sum total of thread times (seconds): {0}", true, this.totalTime / 1000);
this.Print("Total time taken by this program (seconds): {0}", true, (end - start) / 1000);
this.Print("Total bytes: {0}", true, this.totalBytes);
}
/// <summary>
/// download data from the given url
/// </summary>
private void DownloadUrl(int index, string url)
{
using (WebClient client = new WebClient())
{
try
{
int start = Environment.TickCount;
byte[] data = client.DownloadData(url);
int end = Environment.TickCount;
lock (lockObj)
{
this.totalTime = this.totalTime + (end - start);
if (data != null)
{
this.totalBytes = this.totalBytes + data.Length;
}
}
}
catch
{
lock (lockObj) { this.failedCount++; }
}
lock (lockObj)
{
this.completedCount++;
if (this.completedCount % 10000 == 0)
{
this.Print("Completed {0} requests.", true, this.completedCount);
}
}
}
}
/// <summary>
/// print usage of this program
/// </summary>
private void PrintUsage()
{
this.Print("usage: httpbench [options] <url>");
}
/// <summary>
/// print exception message to console
/// </summary>
private void PrintError(string msg, Exception ex = null, params object[] args)
{
StringBuilder sb = new System.Text.StringBuilder();
sb.Append("Error: ");
sb.AppendFormat(msg, args);
if (ex != null)
{
sb.Append("Exception: ");
sb.Append(ex.Message);
}
this.Print(sb.ToString());
}
/// <summary>
/// print to console
/// </summary>
private void Print(string msg, bool isLine = true, params object[] args)
{
if (isLine)
{
Console.WriteLine(msg, args);
}
else
{
Console.Write(msg, args);
}
}
}
}
y resultados:
IIS: httpbench.exe http://localhost/test
Completed 10000 requests.
Completed 20000 requests.
Completed 30000 requests.
Completed 40000 requests.
Completed 50000 requests.
Completed 60000 requests.
Completed 70000 requests.
Completed 80000 requests.
Completed 90000 requests.
Completed 100000 requests.
Total requests sent: 100000
Concurrent threads: 1000
Total completed requests: 100000
Failed requests: 0
Sum total of thread times (seconds): 97
Total time taken by this program (seconds): 16
Total bytes: 2000000
nodejs: httpbench.exe http://localhost:9090/
Completed 10000 requests.
Completed 20000 requests.
Completed 30000 requests.
Completed 40000 requests.
Completed 50000 requests.
Completed 60000 requests.
Completed 70000 requests.
Completed 80000 requests.
Completed 90000 requests.
Completed 100000 requests.
Total requests sent: 100000
Concurrent threads: 1000
Total completed requests: 100000
Failed requests: 0
Sum total of thread times (seconds): 234
Total time taken by this program (seconds): 27
Total bytes: 2000000
conclusión: IIS es más rápido que nodejs en aproximadamente 2,5 veces (en Windows). Esta es una prueba muy rudimentaria, y de ninguna manera concluyente. Pero creo que este es un buen punto de partida. Nodejs probablemente sea más rápido en otros servidores web, en otras plataformas, pero en Windows IIS es el ganador. Los desarrolladores que quieran convertir su ASP.NET MVC en nodejs deben pausar y pensar dos veces antes de continuar.
Actualizado (17/05/2012) Tomcat (en Windows) parece superar IIS sin problemas, aproximadamente 3 veces más rápido que IIS en la distribución de html estático.
gato
index.html at http://localhost:8080/test/
<p>hello, world!</p>
resultados tomcat
httpbench.exe http://localhost:8080/test/
Completed 10000 requests.
Completed 20000 requests.
Completed 30000 requests.
Completed 40000 requests.
Completed 50000 requests.
Completed 60000 requests.
Completed 70000 requests.
Completed 80000 requests.
Completed 90000 requests.
Completed 100000 requests.
Total requests sent: 100000
Concurrent threads: 1000
Total completed requests: 100000
Failed requests: 0
Sum total of thread times (seconds): 31
Total time taken by this program (seconds): 5
Total bytes: 2000000
conclusión actualizada: ejecuté el programa de referencia varias veces. Tomcat parece ser el servidor más rápido en distribuir HTML ESTÁTICO, EN WINDOWS.
Actualizado (18/05/2012) Anteriormente tenía 100.000 solicitudes totales con 10.000 solicitudes simultáneas. Lo aumenté a 1,000,000 solicitudes totales y 100,000 solicitudes concurrentes. IIS aparece como el ganador que grita, con Nodejs careing lo peor. He tabularizado los resultados a continuación:
.
He leído mucho acerca de que Node.js es rápido y capaz de acomodar grandes cantidades de carga. ¿Alguien tiene alguna evidencia del mundo real de este frente a otros marcos, particularmente .Net? La mayoría de los artículos que he leído son anecdóticos o no tienen comparaciones con .Net.
Gracias
La principal diferencia que veo es que el nodo .js es un lenguaje de programación dinámico (verificación de tipos), por lo que los tipos deben estar en tiempo de ejecución derivado. Los lenguajes fuertemente tipados como C # .NET teóricamente tienen mucho más potencial que la lucha contra Node .js (y PHP etc.), especialmente donde es un cálculo costoso. Por cierto, el .NET debería tener una mejor interoperación nativa con C / C ++ que el nodo .js.
Los servidores NIO (Node.js, etc.) tienden a ser más rápidos que los servidores BIO. (IIS, etc.) Para respaldar mi reclamo, TechEmpower es una compañía especializada en benchmarks de marcos web . Son muy abiertos y tienen una forma estándar de probar todos los framewrks.
Las pruebas de la ronda 9 son actualmente las más recientes (mayo de 2014). Hay muchos sabores de IIS probados, pero aspnet-stripped parece ser la variante de IIS más rápida.
Aquí están los resultados en respuestas por segundo (más alto es mejor):
- Serialización JSON
- nodejs:
228,887
- aspnet-stripped:
105,272
- nodejs:
- Single Query
- nodejs-mysql:
88,597
- aspnet-stripped-raw:
47,066
- nodejs-mysql:
- Múltiples consultas
- nodejs-mysql:
8,878
- aspnet-stripped-raw:
3,915
- nodejs-mysql:
- Texto sin formato
- nodejs:
289,578
- aspnet-stripped:
109,136
- nodejs:
En todos los casos, Node.js tiende a ser 2 veces más rápido que IIS.
Ser RÁPIDO y manejar mucha CARGA son dos cosas diferentes. Un servidor que sea realmente RÁPIDO en el servicio de una solicitud por segundo puede quebrar totalmente si lo envía 500 solicitudes por segundo (bajo LOAD ).
También debe considerar las páginas estáticas (y en caché) frente a las dinámicas. Si le preocupan las páginas estáticas, entonces IIS probablemente vencerá al nodo porque IIS utiliza el almacenamiento en caché en modo kernel, lo que significa que las solicitudes que soliciten una página estática ni siquiera saldrán del kernel.
Supongo que estás buscando una comparación entre ASP.NET y el nodo. En esta batalla, después de que todo ha sido compilado / interpretado, probablemente vas a estar bastante cerca en rendimiento. Quizás .NET esté un poco MÁS RÁPIDO o tal vez el nodo esté un poco MÁS RÁPIDO , pero probablemente esté lo suficientemente cerca como para que no te importe. Apostaría por .NET, pero no estoy seguro.
El lugar donde ese nodo es realmente atractivo es para manejar LOAD . Aquí es donde las tecnologías realmente difieren. ASP.NET dedica un hilo para cada solicitud desde su grupo de subprocesos, y una vez que ASP.NET ha agotado todas las solicitudes de subprocesos disponibles, comienzan a ponerse en cola. Si está sirviendo aplicaciones de "Hello World" como el ejemplo de @shankar, entonces esto podría no importar mucho porque los hilos no van a ser bloqueados y podrá manejar una gran cantidad de solicitudes antes que usted quedarse sin hilos. El problema con el modelo ASP.NET se produce cuando comienza a realizar solicitudes de E / S que bloquean el hilo (llamar a un DB, realizar una solicitud http a un servicio, leer un archivo del disco). Estas solicitudes de bloqueo significan que su hilo valioso del grupo de subprocesos no está haciendo nada. Cuantos más bloqueos tengas, menor será LOAD que tu aplicación ASP.NET podrá ofrecer.
Para evitar este bloqueo, utiliza puertos de finalización de E / S que no requieren mantener un hilo mientras espera una respuesta. ASP.NET admite esto, pero desafortunadamente muchos de los frameworks / bibliotecas comunes en .NET NO. Por ejemplo, ADO.NET admite puertos de finalización de E / S, pero Entity Framework no los usa. Así que puedes construir una aplicación ASP.NET que sea puramente asíncrona y maneje mucha carga, pero la mayoría de las personas no lo hace porque no es tan fácil como construir una que sea sincrónica, y es posible que no puedas usar algunas de tus partes favoritas del marco (como linq a entidades) si lo hace.
El problema es que ASP.NET (y el .NET Framework) se crearon para no opinar sobre la E / S asincrónica. A .NET no le importa si escribe código síncrono o asíncrono, por lo que depende del desarrollador tomar esta decisión. Parte de esto se debe a que el enhebrado y la programación con operaciones asíncronas se pensaba que era "difícil", y .NET quería hacer felices a todos (noobs y expertos). Se hizo aún más difícil porque .NET terminó con 3-4 patrones diferentes para hacer asincrónico. .NET 4.5 está intentando retroceder y actualizar el .NET Framework para tener un modelo obstinado en async IO, pero puede pasar un tiempo hasta que los frameworks que realmente te importan lo soporten.
Los diseñadores de nodo, por otro lado, hicieron una elección obstinada de que TODAS las E / S deberían ser asincrónicas. Debido a esta decisión, los diseñadores de nodos también pudieron tomar la decisión de que cada instancia de nodo tuviera un solo subproceso para minimizar la conmutación de subprocesos, y que un subproceso solo ejecutaría el código que se había puesto en cola. Esa podría ser una nueva solicitud, podría ser la devolución de llamada de una solicitud de base de datos, podría ser la devolución de llamada de una solicitud de resto de http que realizó. Nodo intenta maximizar la eficiencia de la CPU al eliminar los conmutadores de contexto de subprocesos. Debido a que node tomó esta obstinada elección de que TODAS las E / S son asincrónicas, eso también significa que todos sus marcos / complementos admiten esta opción. Es más fácil escribir aplicaciones que son 100% asíncronas en el nodo (porque el nodo te obliga a escribir aplicaciones que son asíncronas).
De nuevo, no tengo ningún número difícil para probar de una forma u otra, pero creo que node ganará la competencia LOAD para la aplicación web típica. Una aplicación .NET altamente optimizada (100% asincrónica) podría dar como resultado que la aplicación node.js equivalente se ejecute por su dinero, pero si tomó un promedio de todas las aplicaciones .NET y todas las aplicaciones de nodo, en promedio el nodo probablemente maneje más CARGA.
Espero que ayude.
Tengo que estar de acuerdo con Marcus Granstrom. El escenario es muy importante aquí.
Para ser sincero, parece que estás tomando una decisión arquitectónica de alto impacto. Mi consejo sería aislar las áreas de preocupación y hacer un "horneado" entre las pilas que esté considerando.
Al final del día, usted es responsable de la decisión y no creo que la excusa "Un tipo en me mostró un artículo que decía que estaría bien". Lo cortará con su jefe.