node.js Leistung mit zeromq vs. Python vs. Java
Ich geschrieben habe, ein einfaches echo request/reply-test für zeromq mit node.js, Python, und Java. Der code läuft eine Schleife von 100K Anfragen. Die Plattform ist ein 5yo MacBook Pro mit 2 Kernen und 3G RAM mit Snow Leopard.
node.js ist durchweg eine Größenordnung langsamer als die anderen beiden Plattformen.
Java:
real 0m18.823s
user 0m2.735s
sys 0m6.042s
Python:
real 0m18.600s
user 0m2.656s
sys 0m5.857s
node.js:
real 3m19.034s
user 2m43.460s
sys 0m24.668s
Interessanterweise mit Python und Java client-und server-Prozesse, die beide mit etwa der Hälfte einer CPU. Der client für node.js nur über eine vollwertige CPU und der server verbraucht etwa 30% von einer CPU. Der client-Prozess hat auch eine enorme Anzahl von seitenfehlern führt mich zu glauben, das ist ein Speicher-Problem. Auch bei 10K Anfragen Knoten ist nur 3 mal langsamer; es ist definitiv verlangsamt sich mehr, je länger es läuft.
Hier ist der client-code (beachten Sie, dass der Prozess.exit() Zeile funktioniert nicht, entweder, das ist der Grund, warum ich einen internen timer zusätzlich zu den time-Befehl):
var zeromq = require("zeromq");
var counter = 0;
var startTime = new Date();
var maxnum = 10000;
var socket = zeromq.createSocket('req');
socket.connect("tcp://127.0.0.1:5502");
console.log("Connected to port 5502.");
function moo()
{
process.nextTick(function(){
socket.send('Hello');
if (counter < maxnum)
{
moo();
}
});
}
moo();
socket.on('message',
function(data)
{
if (counter % 1000 == 0)
{
console.log(data.toString('utf8'), counter);
}
if (counter >= maxnum)
{
var endTime = new Date();
console.log("Time: ", startTime, endTime);
console.log("ms : ", endTime - startTime);
process.exit(0);
}
//console.log("Received: " + data);
counter += 1;
}
);
socket.on('error', function(error) {
console.log("Error: "+error);
});
Server-code:
var zeromq = require("zeromq");
var socket = zeromq.createSocket('rep');
socket.bind("tcp://127.0.0.1:5502",
function(err)
{
if (err) throw err;
console.log("Bound to port 5502.");
socket.on('message', function(envelope, blank, data)
{
socket.send(envelope.toString('utf8') + " Blancmange!");
});
socket.on('error', function(err) {
console.log("Error: "+err);
});
}
);
Zum Vergleich, die Python-client-und server-code:
import zmq
context = zmq.Context()
socket = context.socket(zmq.REQ)
socket.connect("tcp://127.0.0.1:5502")
for counter in range(0, 100001):
socket.send("Hello")
message = socket.recv()
if counter % 1000 == 0:
print message, counter
import zmq
context = zmq.Context()
socket = context.socket(zmq.REP)
socket.bind("tcp://127.0.0.1:5502")
print "Bound to port 5502."
while True:
message = socket.recv()
socket.send(message + " Blancmange!")
Und der Java client-und server-code:
package com.moo.test;
import org.zeromq.ZMQ;
import org.zeromq.ZMQ.Context;
import org.zeromq.ZMQ.Socket;
public class TestClient
{
public static void main (String[] args)
{
Context context = ZMQ.context(1);
Socket requester = context.socket(ZMQ.REQ);
requester.connect("tcp://127.0.0.1:5502");
System.out.println("Connected to port 5502.");
for (int counter = 0; counter < 100001; counter++)
{
if (!requester.send("Hello".getBytes(), 0))
{
throw new RuntimeException("Error on send.");
}
byte[] reply = requester.recv(0);
if (reply == null)
{
throw new RuntimeException("Error on receive.");
}
if (counter % 1000 == 0)
{
String replyValue = new String(reply);
System.out.println((new String(reply)) + " " + counter);
}
}
requester.close();
context.term();
}
}
package com.moo.test;
import org.zeromq.ZMQ;
import org.zeromq.ZMQ.Context;
import org.zeromq.ZMQ.Socket;
public class TestServer
{
public static void main (String[] args) {
Context context = ZMQ.context(1);
Socket socket = context.socket(ZMQ.REP);
socket.bind("tcp://127.0.0.1:5502");
System.out.println("Bound to port 5502.");
while (!Thread.currentThread().isInterrupted())
{
byte[] request = socket.recv(0);
if (request == null)
{
throw new RuntimeException("Error on receive.");
}
if (!socket.send(" Blancmange!".getBytes(), 0))
{
throw new RuntimeException("Error on send.");
}
}
socket.close();
context.term();
}
}
Ich würde gerne wie ein Knoten, aber mit dem großen Unterschied in der code-Größe, Einfachheit und Leistung, ich würde haben eine harte Zeit, die überzeugen mich an diesem Punkt.
So, hat jemand gesehen Verhalten, wie dies vor, oder habe ich etwas asinine in den code?
InformationsquelleAutor der Frage Scott A | 2011-07-11
Du musst angemeldet sein, um einen Kommentar abzugeben.
Verwenden Sie eine Dritte Partei C++ - Bindung. Soweit ich es verstehe, ist das crossover zwischen den v8 ' s "js-land" und Bindungen zu v8 in der Programmiersprache "c++ - land", ist sehr teuer. Wenn Sie bemerken, einige beliebt Datenbank Bindungen für die Knoten implementiert sind komplett in JS (obwohl, teilweise bin ich mir sicher, weil die Menschen nicht wollen, zu kompilieren Dinge, sondern auch, weil es das Potenzial hat, sehr schnell).
Wenn ich mich richtig erinnere, als Ryan Dahl war das schreiben der Buffer-Objekte für Knoten, bemerkte er, dass Sie waren tatsächlich viel schneller, wenn er umgesetzt wird Sie vor allem in JS im Gegensatz zu C++. Er endete das schreiben, was er hatte, um in C++und Tat alles, was sonst in pure javascript.
So, ich vermute, ein Teil des performance-Problem hier hat damit zu tun, dass insbesondere Modul ist eine c++ - Bindung.
Urteilen Knoten der Leistung basierend auf einem third-party-Modul ist kein gutes medium für die Bestimmung der Geschwindigkeit oder Qualität. Sie würde viel besser zu benchmark-Knoten native TCP-Schnittstelle.
InformationsquelleAutor der Antwort chjj
"können Sie versuchen, die Logik zu simulieren, aus Ihrem Python-Beispiel (e.ich schicke nächste Nachricht erst nach dem Empfang zurück)?" – Andrej sidorowym Jul 11 at 6:24
Ich denke, das ist ein Teil davon:
Diese version nicht haben die gleiche Erhöhung der Langsamkeit als die vorherigen, wahrscheinlich, weil es nicht werfen Sie so viele Anfragen wie möglich auf dem server und nur die zählen Antworten wie die vorangegangene version. Es ist etwa 1,5-mal so langsam wie Python/Java im Gegensatz zu 5-10 mal langsamer als die Vorherige version.
Immer noch nicht eine beeindruckende Auszeichnung von Knoten für diesen Zweck, aber sicherlich viel besser als "miserabel".
InformationsquelleAutor der Antwort Scott A
Dies war ein problem mit der zeroMQ-Bindungen-Knoten.
Ich weiß nicht seit Wann, aber es wird behoben und Sie erhalten die gleichen Ergebnisse wie mit den anderen Sprachen.
InformationsquelleAutor der Antwort Dan Milon
Ich bin noch nicht ganz so vertraut mit node.js aber die Art und Weise, die Sie ausführen, es ist rekursiv erstellen von neuen Funktionen, die über und über wieder, kein Wunder, es ist die Sprengung. um auf Augenhöhe mit python oder java, der code muss werden mehr entlang den Linien von:
InformationsquelleAutor der Antwort madprogrammer
Performance-Tests mit REQ/REP-buchsen wird verzerrt werden durch "round-tripping" - und thread-Latenzen. Sie sind im Grunde aufwachen den ganzen Stapel, den ganzen Weg nach unten und nach oben, für jede Nachricht. Es ist nicht sehr sinnvoll, da eine Metrik, weil REQ/REP-Fälle sind nie high performance (Sie können nicht). Es gibt zwei bessere performance tests:
InformationsquelleAutor der Antwort Pieter Hintjens
Ihre client python-code, ist die Blockierung in der Schleife. In den Knoten Beispiel, Sie erhalten die Ereignisse in der 'Meldung' event-handler asynchron. Wenn alles, was Sie möchten, von Ihrem client zum empfangen von Daten von zmq dann Ihre python-code wird effizienter, da es codiert ist als spezialisierter one-trick pony. Wenn Sie möchten, das hinzufügen von Funktionen wie hören andere Ereignisse, die nicht mit zmq, dann finden Sie es kompliziert, zu re-schreiben Sie die python-code zu tun. Mit Knoten, alles, was Sie brauchen, ist zum hinzufügen einer weiteren event-handler. Knoten wird nie ein performance-Biest für einfache Beispiele. Jedoch, wie Ihr Projekt wird komplizierter mit mehr bewegliche Teile, ist es viel einfacher, um Funktionen hinzuzufügen richtig zu Knoten, als dies mit der Vanille-python, die Sie geschrieben haben. Ich würde viel eher ein bisschen mehr Geld auf der hardware, erhöhen Sie die Lesbarkeit und die Abnahme meiner Entwicklung Zeit/Kosten.
InformationsquelleAutor der Antwort mna