2017-02-13 10 views
0

Ich versuche, eine Netzwerk-Transfer-Anwendung zu schreiben.Ist ZeroMQ langsamer als Boost Asio?

Die Daten sind binäre Daten und jede Paketgröße ist meist 800KB.

Der Client erzeugt 1000 Daten pro Sekunde. Ich möchte Daten so schnell wie möglich übertragen.

Wenn ich ZeroMQ verwende, erreicht die Geschwindigkeit 350 Daten pro Sekunde, aber der Boost Asio trifft 400 (oder mehr) pro Sekunde.

Wie Sie sehen können, ist die Leistung beider Methoden nicht gut. Das für ZeroMQ verwendete Muster ist ein PUSH/PULL Muster.

Q1: Ich möchte fragen, ist ZeroMQ nur für kleine Nachrichten geeignet?

Q2: Gibt es eine Möglichkeit, die ZeroMQ-Geschwindigkeit zu verbessern?

Q3: Wenn ZeroMQ nicht kann, geben Sie bitte eine gute Methode oder Bibliothek an, um diese Art der Datenübertragung zu verbessern.

Antwort

1

Data Rate

Sie versuchen, 800 MByte/Sekunde zu bewegen. Welche Art von Verbindung ist das? Für eine tcp:// Transportklasse müsste es etwas ziemlich schnelles, z.B. 100 Gbit/s Ethernet, das ist ziemlich exotisch.

Also ich nehme an, dass es eine ipc:// Transportklasse-Verbindung ist. In diesem Fall können Sie eine Verbesserung erzielen, indem Sie ZeroMQ-Zerocopy-Funktionen verwenden, die das wiederholte Kopieren der Daten ersparen.

Bei einer normalen Übertragung müssen Sie Daten in eine zmq-Nachricht kopieren, die in eine ipc-Pipe kopiert, erneut kopiert und auf der Empfängerseite in eine neue zmq-Nachricht zurückkopiert werden muss. All dieses Kopieren erfordert eine Speicherbandbreite von 4 × 800 = 2,4 GByte/s, was, wenn Cache-Konflikte auftreten, einen beträchtlichen Prozentsatz der gesamten Speicherbandbreite eines typischen PC-Systems ausmacht. Mit Zerocopy sollte schneiden Sie das in zwei Hälften.

Alternative to Zero Copy - ohne Umschaltzeit

Wenn Sie ipc:// verwenden, dann sollten die Daten nicht durch die Buchsen senden, sondern Verweise auf die Daten, die durch die Buchsen senden.

Ich habe früher Einsatz von ZMQ gemischt und ein Semaphor gesperrt C++ stl::queue, mit ZMQ einfach für sie Muster (PUSH/PULL in meinem Fall) sind, die stl::queue gemeinsame Zeiger auf Daten zu tragen, und die Daten immer noch verlassen. Der Absender sperrt die Warteschlange, fügt einen gemeinsamen Zeiger ein und sendet dann eine einfache Nachricht (z. B. "1") durch einen zmq-Socket. Der Empfänger liest die "1" und verwendet diese als einen Hinweis, um die Warteschlange zu sperren und einen geteilten Zeiger davon abzuziehen.Somit wurde ein geteilter Zeiger auf Daten von einem Thread zu einem anderen in einem ZMQ-Muster über eine stl::queue übertragen, aber die Daten selbst sind still geblieben. Alles, was ich getan habe, ist Besitz der Daten zwischen Threads übergeben. Es funktioniert so lange, wie der gemeinsame Zeiger, den das Senden hat, unmittelbar nach dem Senden aus dem Gültigkeitsbereich hinausgeht und nicht von dem Absender verwandt wird, um die Daten zu ändern, oder auf die Daten zuzugreifen.

PUSH/PULL ist nicht zu schlecht zu behandeln - jede Nachricht geht an nur einen Empfänger. Es würde mehr Aufwand erfordern, eine solche Mischung mit PUB/SUB zu erstellen, und empfangene Nachrichten müssten als schreibgeschützt behandelt werden, da jeder Empfänger einen gemeinsamen Zeiger auf den gleichen Datenblock wie alle anderen haben würde.

Nachrichtengröße

Ich habe nicht Ahnung, wie groß ein Stück zmqtp zu einer Zeit überträgt, aber ich würde vermuten, dass es in Bezug auf Protokoll relativ effizient ist: Daten-Verhältnis.

+0

@ user3666197, danke für das Aufpolieren! – bazza