Node.js vs .Net performance


183

Ho letto molto sul fatto che Node.js è veloce e in grado di supportare grandi quantità di carico. Qualcuno ha qualche prova del mondo reale di questo rispetto ad altri framework, in particolare .Net? La maggior parte degli articoli che ho letto sono aneddotici o non hanno confronti con .Net.

Grazie


1
Potresti essere più preciso in che tipo di scenario stiamo parlando?
Marcus Granström,

1
Sono interessato a qualsiasi confronto delle prestazioni di .Net e Node.js per applicazioni Web comparabili in esecuzione in IIS.
David Merrilees,

1
Non riesco a immaginare nessuno che stia costruendo un sito web con un alto livello di perf requisiti da .Net. Il problema più basilare che potresti incontrare è che non sarà molto conveniente in termini di licenze, dal momento che ha un alto livello. i siti di solito richiedono il ridimensionamento. E no, non sono un odiatore di .Net. .Net paga le bollette.
Shane Courtrille,

4
Ho dovuto fare test interni di una piccola API REST usando Node / express / mongo e il nuovo webnet .net / mongo e c'erano differenze perf basate su ciò che il cliente voleva, ma alla fine, non abbastanza per fare un differenza. Devi sviluppare i tuoi test in base ai tuoi scenari. Ci sono voluti tre giorni per scrivere le diverse API in entrambe le lingue e poi un altro paio di giorni per impostare correttamente i test. Se hai intenzione di fare qualcosa di remoto, ti suggerirei di impostare i test in base alle tue esigenze e decidere da solo quale sia il migliore per il tuo carico.
AlexGad,

5
@ShaneCourtrille Stai confondendo .Net (un framework) e Windows (un sistema operativo). Sono cose molto diverse e non ci sono requisiti di licenza per .Net (che funziona abbastanza bene su Linux come Mono).
Rainabba,

Risposte:


366

Essere VELOCI e gestire un sacco di LOAD sono due cose diverse. Un server che è davvero VELOCE nel servire una richiesta al secondo potrebbe gracchiare totalmente se lo invii 500 richieste al secondo (sotto LOAD ).

Devi anche considerare le pagine statiche (e memorizzate nella cache) rispetto alle pagine dinamiche. Se sei preoccupato per le pagine statiche, probabilmente IIS batterà il nodo perché IIS utilizza la cache in modalità kernel, il che significa che le richieste che richiedono una pagina statica non usciranno nemmeno dal kernel.

Immagino che tu stia cercando un confronto tra ASP.NET e il nodo. In questa battaglia, dopo che tutto sarà stato compilato / interpretato, probabilmente sarai abbastanza vicino nelle prestazioni. Forse .NET è un po 'più veloce o forse il nodo è un po' più veloce , ma probabilmente è abbastanza vicino che non ti interessa. Scommetto su .NET, ma non lo so per certo.

Il posto in cui il nodo è davvero avvincente è per gestire LOAD . Questo è dove le tecnologie differiscono davvero. ASP.NET dedica un thread per ogni richiesta dal suo pool di thread e, una volta esaurito ASP.NET, tutte le richieste di thread disponibili iniziano ad essere messe in coda. Se stai offrendo app "Hello World" come nell'esempio di @shankar, questo potrebbe non importare molto perché i thread non verranno bloccati e sarai in grado di gestire molte richieste prima di te a corto di discussioni. Il problema con il modello ASP.NET si presenta quando si iniziano a fare richieste I / O che bloccano il thread (chiamare un DB, fare una richiesta http a un servizio, leggere un file dal disco). Queste richieste di blocco indicano che il tuo thread prezioso dal pool di thread non sta facendo nulla. Più blocchi hai,CARICARE la tua app ASP.NET sarà in grado di servire.

Per impedire questo blocco, si utilizzano le porte di completamento I / O che non richiedono il mantenimento di un thread mentre si attende una risposta. ASP.NET supporta questo, ma sfortunatamente molti dei framework / librerie comuni in .NET NON. Ad esempio, ADO.NET supporta le porte di completamento I / O, ma Entity Framework non le utilizza. Quindi puoi creare un'app ASP.NET che è puramente asincrona e gestisce un sacco di carico, ma la maggior parte delle persone non lo fa perché non è facile come costruirne una sincrona e potresti non essere in grado di utilizzare alcune delle tue parti preferite del framework (come linq alle entità) se lo fai.

Il problema è che ASP.NET (e .NET Framework) sono stati creati per essere sconsiderati sull'I / O asincrono. A .NET non importa se si scrive codice sincrono o asincrono, quindi spetta allo sviluppatore prendere questa decisione. Parte di ciò è dovuto al fatto che il threading e la programmazione con operazioni asincrone sono stati ritenuti "difficili" e .NET ha voluto rendere tutti felici (utenti esperti ed esperti). È diventato ancora più difficile perché .NET ha finito con 3-4 diversi schemi per fare asincrono. .NET 4.5 sta provando a tornare indietro e ad aggiornare il framework .NET per avere un modello supponente attorno all'IO asincrono, ma potrebbe passare un po 'di tempo prima che i framework a cui tieni effettivamente lo supportino.

I progettisti del nodo, d'altra parte, hanno fatto una scelta supponente che TUTTO I / O dovrebbe essere asincrono. A causa di questa decisione, i progettisti di nodi sono stati anche in grado di prendere la decisione che ogni istanza del nodo sarebbe a thread singolo per minimizzare il cambio di thread e che un thread avrebbe semplicemente eseguito il codice che era stato messo in coda. Potrebbe essere una nuova richiesta, potrebbe essere la richiamata da una richiesta DB, potrebbe essere la richiamata da una richiesta di riposo http effettuata. Il nodo cerca di massimizzare l'efficienza della CPU eliminando gli switch di contesto del thread. Poiché il nodo ha fatto questa scelta supponente che TUTTI I / O sono asincroni, ciò significa anche che tutti i suoi framework / componenti aggiuntivi supportano questa scelta. È più semplice scrivere app asincrone al 100% nel nodo (perché il nodo ti obbliga a scrivere app asincrone).

Ancora una volta, non ho numeri concreti da dimostrare in un modo o nell'altro, ma penso che il nodo vincerebbe il concorso LOAD per la tipica app web. Un'app .NET altamente ottimizzata (100% asincrona) potrebbe far funzionare l'app equivalente node.js per i suoi soldi, ma se hai preso una media di tutte le .NET e tutte le app di nodi là fuori, in media il nodo probabilmente ne gestisce di più CARICARE.

Spero che aiuti.


39
Ricorda che ASP.NET ha supportato i gestori di richieste asincrone per molto tempo e con MVC4 sono diventati estremamente semplici da usare.
fabspro,

12
"Queste richieste di blocco significano che il tuo thread prezioso dal pool di thread non sta facendo nulla. Più blocchi hai, meno LOAD sarà in grado di servire la tua app ASP.NET." Perché importa se facciamo la coda (la richiesta in arrivo) o nel back-end (il thread di lavoro effettivo)? In ogni caso, la richiesta del client è in attesa di risposta. Penso che la chiave che le persone trascurano in questo dibattito sia "Throughput". Non si tratta di quante connessioni simultanee un server detiene, è quanto velocemente può rispondere a ciascuna richiesta, giusto?
sabato

19
// Non mi lascia modificare il mio commento, quindi ecco cosa intendevo dire.// @sjdirect - La velocità effettiva non è la stessa del tempo di risposta. Hai ragione a preoccuparti del tempo di risposta, ma è una scelta tra tempo di coda + tempo di risposta o solo tempo di risposta. L'elaborazione della richiesta richiederà altrettanto tempo in entrambi gli scenari (L'esecuzione in modo sincrono NON farà eseguire la richiesta DB più velocemente), ma se i thread della richiesta sono bloccati, si aggiungono anche i tempi di coda alle richieste perché non è nemmeno possibile avviare l'elaborazione della richiesta fino a quando non vengono eseguite le richieste precedenti.
Matt Dotson,

6
Questo è stato davvero istruttivo, grazie! Una cosa da notare è che Entity Framework 6 (attualmente RC1) ora supporta il modello asincrono da .NET 4.5. msdn.microsoft.com/en-us/data/jj819165
parlamento

4
Questo è estremamente speculativo! Sarebbe bello avere dei dati. Di solito è così che decido come procedere con argomenti di performance.
KingPuppy,

50

Ho fatto un test di prestazione rudimentale tra nodejs e IIS. IIS è circa 2,5 volte più veloce di nodejs quando viene visualizzato "ciao, mondo!". codice sotto.

il mio hardware: Dell Latitude E6510, Core i5 (dual core), 8 GB RAM, Windows 7 Enterprise 64 bit OS

server nodo

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>

il mio programma di benchmark utilizzando la libreria di task paralleli:

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

}
}

e risultati:

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

conclusione: IIS è più veloce di nodejs di circa 2,5 volte (su Windows). Questo è un test molto rudimentale e assolutamente non conclusivo. Ma credo che questo sia un buon punto di partenza. Nodejs è probabilmente più veloce su altri server Web, su altre piattaforme, ma su Windows IIS è il vincitore. Gli sviluppatori che desiderano convertire il proprio MVC ASP.NET in nodejs devono mettere in pausa e riflettere due volte prima di procedere.

Tomcat (su Windows) aggiornato (17/05/2012) sembra battere IIS a mani basse, circa 3 volte più veloce di IIS nel distribuire HTML statico.

micio

index.html at http://localhost:8080/test/
<p>hello, world!</p>

risultati 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

conclusione aggiornata: ho eseguito il programma di riferimento più volte. Tomcat sembra essere il server più veloce nella distribuzione di HTML STATICO, SU WINDOWS.

Aggiornato (18/05/2012) In precedenza avevo 100.000 richieste totali con 10.000 richieste simultanee. L'ho aumentato a 1.000.000 di richieste totali e 100.000 richieste simultanee. IIS esce come il vincitore urlante, con Nodejs che fa la peggiore. Ho tabulato i seguenti risultati:

NodeJS vs IIS vs Tomcat che serve HTML STATICO su WINDOWS.


56
Stai confrontando le mele con i gatti. Confronta Node.js con ASP.NET MVC. Al massimo IIS è più veloce nel servire file statici, anche se ne dubito seriamente.
alessioalex,

12
@alessioalex: non capisco perché questo confronto non sia valido. sto confrontando i tempi di risposta per HTML statico. IIS sta generando html statico da default.htm, mentre il server nodejs sta rivelando la stessa stringa e IIS esce avanti. Il confronto tra un'applicazione ASP.NET MVC richiederebbe più impegno e tempo e sto pianificando di farlo in seguito.
Shankar,

28
Ok, supponiamo che IIS sia migliore nel servire file statici su Windows rispetto a Nodo. IIS serve solo file statici e simili (come Apache o NGINX), Node fa molto di più. Dovresti confrontare ASP.NET MVC con Node (interrogare il database, recuperare dati da un servizio esterno, ecc. Ecc.). Vedrai enormi miglioramenti delle prestazioni con Node su ASP.NET MVC.
alessioalex,

27
Se hai intenzione di farlo, ti preghiamo almeno di capire la natura del nodo. Un processo Node può utilizzare solo un singolo core. Pertanto, ciò che si sta confrontando è un processo di nodo in esecuzione su un core con un processo IIS e tomcat che utilizza più core. Per confrontare correttamente, è necessario eseguire il cluster cluster. Vedi nodejs.org/api/cluster.html per una soluzione cluster semplice da usare. Tuttavia, posso dirti per esperienza, la differenza tra nodo e asincrono c # è del 10-15% in entrambi i modi a seconda di ciò che stai facendo.
AlexGad,

14
Inoltre, testare i file statici con nodo e IIS e Tomcat non ha senso. Prima di tutto, il nodo non è eccezionale per i file statici, ma non è davvero pensato per essere (utilizzare lo strumento giusto per il lavoro giusto). Se qualcuno è preoccupato per la velocità dei propri file statici, dovrebbe comunque utilizzare un CDN.
AlexGad,

26

I server NIO (Node.js ecc.) Tendono ad essere più veloci dei server BIO. (IIS ecc.). A sostegno della mia richiesta, TechEmpower è una società specializzata in benchmark per il framework web . Sono molto aperti e hanno un modo standard di testare tutti i framewrks.

I test del Round 9 sono attualmente gli ultimi (maggio 2014). Esistono molti tipi di IIS testati, ma la rimozione di aspnet sembra essere la variante IIS più veloce.

Ecco i risultati in risposte al secondo (più alto è meglio):

  • Serializzazione JSON
    • nodejs: 228,887
    • aspnet-spogliato: 105,272
  • Query singola
    • nodejs-mysql: 88,597
    • aspnet-spogliato-raw: 47,066
  • Query multiple
    • nodejs-mysql: 8,878
    • aspnet-spogliato-raw: 3,915
  • Testo semplice
    • nodejs: 289,578
    • aspnet-spogliato: 109,136

In tutti i casi, Node.js tende ad essere 2x + più veloce di IIS.


1
Tranne il test Query multiple, in cui ASPNET ha due voci (aspnet-stripped-raw e aspnet-mysql-raw) che entrambe battono nodejs-mysql, che è la voce njs principale.
GalacticCowboy il

4
Bene, il test Query multiple non sta testando esattamente la velocità del server. Sta principalmente testando la velocità del driver MySQL. NodeJS utilizza principalmente database NO-SQL come MongoDB, CouchDB. Il driver MySQL potrebbe non essere ottimizzato. I test di serializzazione Json e Plaintext tendono a fornire al server la massima velocità: mi fiderei di più di loro.
ttekin

cosa succede se utilizzo il nodo IIS? è che la mia performance peggiorerà o sarà la stessa.
Umashankar,

3
Grazie per il link alla pagina di riferimento. Tuttavia, la risposta potrebbe richiedere un aggiornamento, le cose potrebbero essere cambiate un po 'con l'avvento di .NET Core 2.1. Ad esempio, il benchmark di serializzazione JSON 2018 elenca ASP.NET Core a 971.122 richieste / sec e Node.js a 561.593 richieste / sec, quindi oggi ASP.NET Core sembrerebbe essere quasi due volte più veloce di Node.js a tale riguardo.
stakx - non contribuisce più il

13

Sono d'accordo con Marcus Granstrom che lo scenario è molto importante qui.

Ad essere onesti sembra che tu stia prendendo una decisione architettonica di grande impatto. Il mio consiglio sarebbe di isolare le aree di preoccupazione e fare un "travaso" tra le pile che stai prendendo in considerazione.

Alla fine della giornata sei responsabile della decisione e non credo che la scusa "Qualcuno su Stackoverflow mi abbia mostrato un articolo che diceva che sarebbe andato bene" Lo taglierà con il tuo capo.


1
Sto cercando qualcosa per convincere le persone (incluso il mio capo) che vale la pena considerare come alternativa a un sito Web MVC.net, non per convincerle che dovremmo scambiare. Tutto quello che ho trovato finora sono menzioni aneddotiche che possono supportare più carico e prestazioni migliori. Qualcuno lo ha effettivamente dimostrato?
David Merrilees,

17
Ma cosa c'è di sbagliato nel sito Web MVC? PERCHÉ stai cercando di trovare un'alternativa? Questo è il Q più importante. Se il problema è che il cane è lento sotto un pesante carico simultaneo, allora dovresti assicurarti di usare async.net. Se è ancora molto lento, devi scomporre il codice e capire dove si trovano i colli di bottiglia. Nella mia esperienza, non c'è una differenza enorme tra nodo e rete asincrona negli scenari REAL WORLD. Puoi cambiare la tua piattaforma, ma probabilmente cambierai semplicemente un set di colli di bottiglia / mal di testa del codice per un altro set di colli di bottiglia / mal di testa del codice.
AlexGad,

1

La principale differenza che vedo è che il nodo .js è un linguaggio di programmazione dinamico (verifica del tipo), quindi i tipi devono essere derivati ​​in fase di esecuzione. I linguaggi fortemente tipizzati come C # .NET hanno teoricamente un potenziale molto maggiore vince la lotta contro Nodo .js (e PHP ecc.), In particolare laddove è costoso il calcolo. A proposito, .NET dovrebbe avere una migliore interazione nativa con C / C ++ rispetto al nodo .js.


4
Il tuo suggerimento che la digitazione "debole" in JS lo rallenta è sbagliato e irrilevante e, a prescindere, sta confrontando Mele e Pietre (anche le Arance sarebbero più simili a quelle che stai suggerendo).
Rainabba,

7
@rainabba Quando si confronta un calcolo di qualche tipo (ad esempio fibonacci di x), è completamente corretto.
Stan,

5
@steve In realtà, dato Z, non puoi ancora dirlo perché JS è un linguaggio e .Net è un framework. Sono cose completamente diverse. I runtime .Net sono compilati per una particolare architettura di processore e quindi non è possibile modificare in modo significativo le prestazioni di un determinato blocco di codice per un singolo componente hardware. Come mostra V8, JS può essere interpretato ed eseguito e con velocità estremamente variabili e non c'è motivo di pensare che un giorno il tuo codice fibonacci scritto in JS non funzionerà SOLO come con il codice eseguito attraverso il CLR (probabilmente, sarà Più veloce). Mele e Pietre; come ho detto.
Rainabba,

1
forse hai ragione, ma a mio avviso, non conosco altri paesi, in Cina, molti molti programmatori che ho intervistato appena conosciuto EF o Linq a Sql, questi framework riducono significativamente le prestazioni di .net
dexiang

1
La stessa cosa si può dire a JS. mentre JS sta raggiungendo Fibonacci, pensi davvero che .NET rimarrà dove sta aspettando?
quanben,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.