Die Zuteilungslatenz scheint hoch, warum?

8

Ich habe eine (Java) -Anwendung, die in einer Umgebung mit niedriger Latenz läuft, sie verarbeitet normalerweise Anweisungen in ~ 600 Mikrosekunden (+/- 100). Natürlich, da wir weiter in den Mikrosekundenbereich hineingerückt sind, sehen wir, dass sich die Latenzkosten ändern und wir haben jetzt festgestellt, dass 2/3 dieser Zeit für die Zuweisung der 2 Kerndomänenobjekte aufgewendet wird.

Benchmarking hat die beleidigenden Abschnitte des Codes isoliert, um buchstäblich die Konstruktion der Objekte aus bestehenden Referenzen, dh im Grunde eine Ladung von Referenzen (~ 15 in jeder Klasse) und ein paar Listen neu, obwohl siehe Hinweis unten auf genau was hier gemessen wird.

Jeder nimmt konsistent ~ 100micros, was für mich unerklärlich ist und ich versuche herauszufinden, warum. Ein schneller Benchmark legt nahe, dass ein ähnlich großes Objekt voller Strings etwa 2-3 Mikros zu neuen Ups braucht. Offensichtlich ist diese Art von Benchmark mit Schwierigkeiten behaftet, aber sie könnte als Basis nützlich sein.

Es gibt 2 Qs hier

  • Wie untersucht man diese Art von Verhalten?
  • Welche Erklärungen gibt es für die langsame Zuweisung?

Beachten Sie, dass es sich bei der betroffenen Hardware um Solaris 10 x86 auf Sun X4600 mit 8 * Dual-Core-Opteron @ 3,2GHz

handelt

Zu den Dingen, die wir uns angesehen haben, gehören

  • Das Überprüfen der PrintTLAB-Statistiken zeigt v einige langsame Allocs, so dass dort keine Konflikte auftreten sollten.
  • PrintCompilation schlägt vor, dass eine dieser Codebeispiele nicht JIT-freundlich ist, obwohl Solaris hier anscheinend ein ungewöhnliches Verhalten zeigt (zB gegenüber einem modernen Linux, keinen Linux-ähnlichen Jahrgang zu solaris10, der jetzt auf der Bank ist) / li>
  • LogCompilation ... etwas schwieriger zu parsen, um es gelinde auszudrücken, das ist ein fortlaufender Job, bisher noch nicht offensichtlich
  • JVM Versionen ... konsistent über 6u6 und 6u14, nicht versucht 6u18 oder die letzten 7 noch

Beliebige & amp; Alle Gedanken waren zu schätzen

Eine Zusammenfassung der Kommentare zu verschiedenen Posts, um die Dinge klarer zu machen

  • die Kosten, die ich bemesse, sind die Gesamtkosten für die Erstellung des Objekts, das über einen Builder erstellt wird (wie eines von diese ) und deren privater Konstruktor eine neue ArrayList einige Male aufruft und Referenzen auf existierende Objekte setzt. Die gemessenen Kosten decken die Kosten für das Einrichten des Builders und die Konvertierung des Builders in ein Domänenobjekt
  • ab Die
  • -Kompilierung (nach Hotspot) hat eine deutliche Auswirkung, ist aber immer noch relativ langsam (die Kompilierung nimmt in diesem Fall von 100micros auf ~ 60 herunter)
  • Kompilierung (von Hotspot) auf meinem naiven Benchmark dauert die Zuordnungszeit von ~ 2micros auf ~ 300ns
  • Latenz variiert nicht mit der Sammlung von jungen Genen (ParNew oder Parallele Spülung)
Matt 17.11.2009, 20:36
quelle

5 Antworten

3

Da es bei Ihrer Frage mehr darum ging, wie Sie das Problem untersuchen und nicht "was ist mein Problem", behalte ich einige Tools zum Ausprobieren bei.

Ein sehr nützliches Werkzeug, um eine bessere Vorstellung davon zu bekommen, was gerade passiert und wann es BTrace ist. Es ist ähnlich wie DTrace aber ein reines Java-Tool. In diesem Sinne nehme ich an, dass Sie DTrace kennen, wenn das nicht auch nützlich ist, wenn es nicht stumpf ist. Dadurch erhalten Sie einen Überblick darüber, was in JVM und OS passiert und was passiert.

Oh, noch etwas, das du in deinem ursprünglichen Beitrag klären musst. Welchen Sammler läufst du? Ich nehme an mit hohem Latenz-Problem, dass Sie einen niedrigen Pausen-Kollektor wie CMS verwenden. Wenn ja, hast du eine Abstimmung versucht?

    
reccles 18.11.2009 13:45
quelle
3

Wenn Sie dieselbe Aufgabe oft wiederholen, läuft Ihre CPU sehr effizient. Dies liegt daran, dass Ihre Cache-Fehlzeiten und das Aufwärmen der CPU nicht als Faktor angezeigt werden. Es ist auch möglich, dass Sie Ihre JVM-Warmzeit nicht berücksichtigen.

Wenn Sie das gleiche versuchen, wenn die JVM und / oder die CPU nicht warmgelaufen ist. Sie werden ein ganz anderes Ergebnis erhalten.

Versuchen Sie dasselbe zu tun, sagen Sie 25 Mal (weniger als Ihre Kompilierungsschwelle) und schlafen Sie (100) zwischen den Tests. Sie sollten erwarten, viel höhere Zeiten zu sehen, näher an dem, was Sie in der realen Anwendung sehen.

Das Verhalten Ihrer App unterscheidet sich jedoch, um meinen Standpunkt zu verdeutlichen. Ich habe festgestellt, dass Warten auf IO mehr störend sein kann als ein normaler Schlaf.

Wenn Sie Ihren Benchmark durchführen, sollten Sie versuchen, sicherzustellen, dass Sie mit Gleichem vergleichen.

%Vor%     
Peter Lawrey 06.01.2010 21:01
quelle
2

Die Speicherzuweisung kann zu Nebenwirkungen führen. Ist es möglich, dass die Speicherzuweisung dazu führt, dass der Heap komprimiert wird? Haben Sie nachgesehen, ob Ihre Speicherzuordnung dazu führt, dass der GC zur gleichen Zeit ausgeführt wird?

Haben Sie separat festgelegt, wie lange es dauert, um die neuen ArrayLists zu erstellen?

    
RickNZ 18.11.2009 11:06
quelle
2

Es ist wahrscheinlich nicht zu erwarten, dass Latenzzeiten im Mikrosekundenbereich von einer universellen VM, die auf einem Allzweckbetriebssystem ausgeführt wird, selbst mit so großer Hardware garantiert werden. Massiver Durchsatz ist das Beste, auf das Sie hoffen können. Wie wäre es mit dem Wechsel zu einer Echtzeit-VM, wenn Sie eine benötigen (ich spreche RTSJ und all das ...)

... meine zwei Cent

    
Gyom 18.11.2009 11:12
quelle
2

Nur ein paar wilde Vermutungen:

Es ist mein Verständnis, dass Java-VMs den Speicher von kurzlebigen Objekten anders handhaben als Langzeitobjekte. Es scheint mir vernünftig zu sein, dass an dem Punkt, an dem ein Objekt von einer Funktion - einem lokalen Verweis auf Referenzen auf dem globalen Haufen - abgeht, ein großes Ereignis wäre. Anstatt für die Bereinigung beim Beenden der Funktion verfügbar zu sein, muss sie nun vom GC verfolgt werden.

Es kann auch sein, dass die GC-Buchhaltung geändert werden muss, wenn von einer Referenz zu mehreren Referenzen auf ein einzelnes Objekt gewechselt wird. Solange ein Objekt eine einzige Referenz hat, ist es leicht aufzuräumen. Mehrere Referenzen können Referenzschleifen haben und / oder der GC muss in allen anderen Objekten nach der Referenz suchen.

    
Zan Lynx 23.12.2009 15:54
quelle