it-swarm.com.de

Schreiben mit geringer Latenz Java

Gibt es Java-spezifische Techniken (Dinge, die für C++ nicht gelten würden) zum Schreiben von Code mit geringer Latenz in Java? Ich sehe oft Java Rollen mit geringer Latenz und sie fragen nach Erfahrung beim Schreiben von Java mit niedriger Latenz - was manchmal ein bisschen wie ein Oxymoron erscheint.

Der einzige Gedanke, an den ich denken könnte, ist die Erfahrung mit JNI, bei der E/A-Aufrufe an nativen Code ausgelagert werden. Möglicherweise wird auch das Disruptormuster verwendet, aber das ist keine tatsächliche Technologie.

Gibt es Java spezifische Tipps zum Schreiben von Code mit geringer Latenz?

Ich bin mir bewusst, dass es eine Echtzeitspezifikation Java gibt, aber ich wurde gewarnt, dass Echtzeit nicht gleichbedeutend mit geringer Latenz ist.

32
user997112

Zusätzlich zu Martijns Kommentare Ich würde hinzufügen:

  1. Wärmen Sie Ihre JVM auf. Der Bytecode wird zunächst für Hotspot interpretiert und nach 10K-Beobachtungen auf dem Server kompiliert. Tiered Compilation kann eine gute Lücke sein.

  2. Das Laden von Klassen ist ein sequentieller Prozess, der IO auf die Festplatte) umfasst. Stellen Sie sicher, dass alle Klassen für Ihre Haupttransaktionsflüsse im Voraus geladen werden und niemals aus der Perm-Generierung entfernt werden.

  3. Befolgen Sie das " Single Writer Principle ", um Konflikte und die Auswirkungen des Little-Gesetzes auf den Warteschlangeneffekt zu vermeiden, und studieren Sie das Amdhal-Gesetz, um herauszufinden, was parallel sein kann und ob es sich lohnt.

  4. Modellieren Sie Ihre Geschäftsdomäne und stellen Sie sicher, dass alle Ihre Algorithmen O(1) oder mindestens O (log n)) sind. Dies ist meiner Erfahrung nach wahrscheinlich die Hauptursache für Leistungsprobleme. Stellen Sie sicher, dass Sie über Leistung verfügen Tests, um die Hauptfälle abzudecken.

  5. Geringe Latenz in Java ist nicht nur auf Java beschränkt. Sie müssen den gesamten Stapel verstehen, auf dem Ihr Code ausgeführt wird. Dies umfasst die Optimierung des Betriebssystems, die Auswahl der geeigneten Hardware, die Optimierung der Systemsoftware und der Gerätetreiber für diese Hardware.

  6. Sei realistisch. Wenn Sie eine geringe Latenz benötigen, laufen Sie nicht auf einem Hypervisor. Stellen Sie sicher, dass Sie über genügend Kerne für alle Threads verfügen, die sich im ausführbaren Zustand befinden müssen.

  7. Cache-Fehler sind Ihre größten Kosten für die Leistung. Verwenden Sie Algorithmen, die cachefreundlich sind und die Affinität zu Prozessorkernen entweder mit Task-Set oder numactl für eine JVM oder JNI für einzelne Threads festlegen.

  8. Betrachten Sie eine alternative JVM wie Zing von Azul mit einem pausenlosen Garbage Collector.

  9. Am wichtigsten ist, jemanden mit Erfahrung zu beschäftigen. Dies spart Ihnen auf lange Sicht so viel Zeit. Schamloser Stecker :-)

Echtzeit und niedrige Latenz sind deutlich getrennte Themen, obwohl sie oft miteinander verbunden sind. Bei Echtzeit geht es darum, vorhersehbarer als schnell zu sein. Nach meiner Erfahrung sind die Echtzeit-JVMs, auch die weichen Echtzeit-JVMs, langsamer als die normalen JVMs.

38
Martin Thompson

Es gibt eine Reihe von Dingen, die man beachten muss, ja. Ich bin im Moment auf Kreta mit eingeschränktem Netzzugang, daher wird dies (ziemlich) kurz sein. Außerdem bin ich kein Experte für niedrige Latenz, aber einige meiner Kollegen spielen einen im wirklichen Leben :-).

  1. Sie müssen die mechanische Sympathie schätzen (ein Begriff, der von Martin Thompson geprägt wurde). Mit anderen Worten, Sie müssen verstehen, was Ihre zugrunde liegende Hardware tut. Es ist sehr wichtig zu wissen, wie CPUs Cache-Zeilen laden, wie ihre Lese-/Schreibbandbreite ist, wie schnell der Hauptspeicher ist und vieles mehr. Warum? Weil Sie überlegen müssen, wie sich Ihr Java Quellcode) über die Laufzeit-JVM auf das Betriebssystem/die Hardware auswirkt. Dies ist beispielsweise die Art und Weise, wie Ihre Feldvariablen in Ihrem Quellcode angeordnet sind, was zu einer Cache-Zeile führt Räumungen (kostet ~ 150 Taktzyklen), hmmm ... :-).

  2. Im Allgemeinen möchten Sie sperrfreie Algorithmen und E/A. Selbst bei der am besten konzipierten gleichzeitigen Anwendung (die Sperren verwendet) besteht die Gefahr des Blockierens. Das Blockieren bei geringer Latenz ist im Allgemeinen schlecht :-).

  3. Objektzuordnung und Speicherbereinigung verstehen. Dies ist ein massives Thema, aber im Grunde möchten Sie GC-Pausen vermeiden (häufig verursacht durch die Stop the World-Natur verschiedener GC-Sammlungen). Spezialisierte GC-Kollektoren wie der Azul-Kollektor können dieses Problem in vielen Fällen sofort für Sie lösen, aber für die meisten Menschen müssen sie verstehen, wie die Sun/Oracle-GCs (CMS, G1 usw.) optimiert werden.

  4. Der Hotspot JIT ist unglaublich. Erfahren Sie mehr über die Optimierungen, aber im Allgemeinen ermöglichen alle guten OO -Techniken (Kapselung, kleine Methoden, so viele unveränderliche Daten wie möglich)) die Optimierung von JIT, wodurch Sie die Arten von Leistungsstufen erhalten, die gut gestalteter C/C++ - Code bietet Ihnen.

  5. Gesamtsystemarchitektur. Beachten Sie das Netzwerk, den Standort der Maschinen, wenn Sie über Glasfaser usw. mit der Vermittlungsstelle verbunden sind.

  6. Beachten Sie die Auswirkungen der Protokollierung. Es ist wahrscheinlich eine gute Idee, Binärdateien zu protokollieren oder codierte Ausgaben zu verwenden, die Sie offline analysieren können.

Insgesamt empfehle ich dringend, weiterzumachen Kirk Pepperdines Java Performance Tuning-Kurs [Haftungsausschluss: Ich unterrichte diesen Kurs selbst, daher bin ich voreingenommen]. Sie erhalten eine gute Berichterstattung der verschiedenen Aspekte der JVM und ihrer Auswirkungen auf das zugrunde liegende Betriebssystem und die zugrunde liegende Hardware.

PS: Ich werde versuchen, das später noch einmal zu wiederholen und es aufzuräumen.

23
Martijn Verburg