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:
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)
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.
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