Java-Socket-Leistungsengpass: wo?

8

Ich habe vor Kurzem mit der Entwicklung einer Anwendung begonnen, bei der die Vernetzung intensiv genutzt wird. Ein erster Versuch wurde mit RMI gemacht und aus verschiedenen Gründen sind wir auf reine Sockets umgestiegen. Beim Testen von Sockets über ein Netzwerk oder sogar auf localhost sind wir jedoch auf eine Rate von 25 Anfragen / Sekunde gesunken. Bei Verwendung von RMI war es zwei Größenordnungen höher.

Mit ein wenig mehr Tests haben wir folgende (für localhost) erhalten:

  • Immer das gleiche Objekt senden: 31628 Anfragen / Sek.
  • Immer ein neues Objekt senden: 25 Anfragen / Sek
  • Nur Objekt-Erstellungsrate: 3-4 Millionen pro Sekunde (das ist also nicht der Flaschenhals)

Hier ist der Client-Code: (Die Server-Seite antwortet nur mit einem "ACK")

%Vor%

Die TcpRequest-Klasse ist nur eine Dummy-Klasse ohne etwas Besonderes.

Wenn also ein Objekt schnell erstellt wird, wenn es schnell über das Netzwerk gesendet wird ... Warum sendet ein neues Objekt so langsam über das Netzwerk?!?!

Und wenn Sie dasselbe Objekt behalten und seinen Inhalt ändern, bevor Sie es senden, haben Sie auch eine hohe Übertragungsrate ... aber fallen Sie in die unangenehme Falle:

  

Beim Arbeiten mit Objektserialisierung   Es ist wichtig, dies zu beachten   Der ObjectOutputStream verwaltet a   Hashtabelle, die die geschriebenen Objekte abbildet   in den Strom zu einem Griff. Wenn ein   Objekt wird in den Stream geschrieben   das erste Mal wird sein Inhalt sein   kopiert in den Stream. Anschließend   schreibt jedoch ein Handle zu   Das Objekt wird in die. geschrieben   streamen.

... was uns passiert ist und einige Stunden Debugging verursacht hat, bevor wir es herausgefunden haben.

Also im Grunde ... wie erreichen Sie einen hohen Durchsatz mit Sockeln? (... Ich meine, mit RMI als Wrapper waren wir schon zwei Größenordnungen höher!)

Gelöst:

Durch Ersetzen:

%Vor%

Mit:

%Vor%

Die Leistungen sind wieder normal (fast der gleiche hohe Durchsatz wie bei dem gleichen Objektfall)

    
dagnelies 15.12.2010, 15:08
quelle

3 Antworten

7

Es gefunden:

Anstelle von:

%Vor%

Sie sollten verwenden:

%Vor%

Und

%Vor%

beim Senden einer Nachricht.

... macht einen großen Unterschied ... obwohl ich nicht genau weiß warum.

    
dagnelies 15.12.2010, 15:17
quelle
1

Ich würde den Ergebnissen dieser Benchmark nicht trauen. Es stellt nicht sicher, dass die JVM aufgewärmt ist; d.h., dass Klassen vor dem Messen der Ausführungszeiten geladen, initialisiert und zu nativem Code kompiliert werden. Es besteht eine gute Chance, dass die Kompilierung von nativem Code durch die Ausführung des Benchmarks teilweise ausgelöst wird, was die Zeit für eine oder mehrere der Schleifen in die Höhe treibt.

    
Stephen C 15.12.2010 15:18
quelle
0

Das Problem, auf das Sie stoßen, ist kein niedriger Durchsatz mit Sockets; Es ist langsam Standard-Java-Serialisierung.

Wenn Sie dasselbe Objekt immer wieder senden, wird es nur einmal serialisiert, und jedes Mal wird ein Verweis darauf gesendet. Das erklärt, warum es so schnell geht.

Wenn Sie jedes Mal ein neues Objekt erstellen, muss dieses neue Objekt mit dem relativ langsamen Java-Serialisierungsmechanismus serialisiert werden, der wahrscheinlich auch viel komplexer ist als das, was Sie brauchen.

Was Sie tun können, um dies zu verbessern, ist entweder das Implementieren von benutzerdefiniertem Serialisierungscode für Ihre Klasse oder das Erstellen eines eigenen Objektsserialisierungsprotokolls außerhalb der Klasse (und DataOutput anstelle von ObjectOutputStream verwenden).

Dieser Artikel hat viele gute Informationen, auch wenn es etwas veraltet ist: Ссылка Siehe den letzten Teil zu Leistungsaspekten

    
Gabriel Reid 15.12.2010 15:18
quelle

Tags und Links