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

Schreibe einen Kommentar