Hinweis:
- Dieses Tutorial ist in einer von Oracle bereitgestellten kostenlosen Übungsumgebung verfügbar.
- Es verwendet Beispielwerte für Oracle Cloud Infrastructure-Zugangsdaten, -Mandanten und -Compartments. Wenn Sie Ihre Übung abgeschlossen haben, ersetzen Sie diese Werte durch die Werte, die für Ihre Cloud-Umgebung spezifisch sind.
Cloud-native Java-Anwendungen mit GraalVM Enterprise PGO optimieren
Einführung
In dieser Übung wird gezeigt, wie Sie eine Java Microbenchmark Harness-(JMH-)Benchmark als native ausführbare Datei ausführen, die mit GraalVM Native Image erstellt wurde, und Profile-Guided Optimization (PGO) anwenden, um die Performance zu verbessern.
Mit GraalVM Native Image können Sie eine Java-Anwendung in einer nativen ausführbaren Datei kompilieren, die fast sofort beginnt und weniger Arbeitsspeicher und CPU erfordert.
Profile-Guided Optimization (PGO) ist eine häufig verwendete Technik im Java-Ökosystem, um die fehlende Just-in-Time-Optimierung zu mildern und die Ausführungsprofile bei einer Ausführung zu erfassen und sie dann zur Optimierung der nachfolgenden Kompilierung(en) zu verwenden. Mit PGO können Sie die Profiling-Daten erfassen und an das Tool native-image
übergeben. Anhand dieser Informationen wird die Performance der resultierenden ausführbaren Datei weiter optimiert.
Hinweise zur Verwendung von JMH mit GraalVM Native Image
Bei der Ausführung auf der JVM forkiert JMH eine neue JVM für jede Benchmark, um sicherzustellen, dass die Messungen für jede Benchmark nicht beeinträchtigt werden. Dieser Ansatz ist bei der Verwendung von GraalVM Native Image nicht möglich. Daher sollten Sie die folgende Anleitung beim Erstellen von JMH-Benchmarks berücksichtigen, die als native ausführbare Dateien ausgeführt werden sollen:
- Einzelnes Benchmark in jede native ausführbare Datei aufnehmen
- Annotieren Sie die Benchmark mit
@Fork(0)
, um sicherzustellen, dass die Benchmark nicht verzweigt ist- Wenn Sie die Benchmark so profilieren möchten, dass eine optimierte Benchmark generiert wird, ignorieren Sie die Benchmarkergebnisse bei der Profilerstellung.
Hinweis: Oracle Cloud Infrastructure (OCI) stellt GraalVM Enterprise ohne zusätzliche Kosten bereit.
Übungsziele
In dieser Übung führen Sie folgende Schritte aus:
- Verbindung zu einem Remotehost in Oracle Cloud herstellen
- JMH-Benchmark auf JVM kompilieren und ausführen
- Erstellen Sie diese JMH-Benchmark mit GraalVM Native Image in einer nativen ausführbaren Datei, und führen Sie sie aus
- Native ausführbare Version mit PGO optimieren und ausführen
Geschätzte Übungszeit: 30-45 Minuten
HINWEIS: Wenn das Laptopsymbol in den Anweisungen angezeigt wird, müssen Sie einen Befehl eingeben. Achte darauf.
# This is where we you will need to do something
Um einen Befehl zu kopieren, bewegen Sie den Mauszeiger über das Feld, und klicken Sie dann auf das Symbol In Zwischenablage kopieren.
Um einen kopierten Befehl in ein Terminalfenster einzufügen, klicken Sie mit der rechten Maustaste, und wählen Sie die Option Einfügen aus dem Kontextmenü. Wenn Sie stattdessen Tastenkombinationen bevorzugen, verwenden Sie CTRL+SHIFT+V
.
Schritt 1: Verbindung mit einem Remotehost herstellen und Entwicklungsumgebung prüfen
Ihre Entwicklungsumgebung wird von einem Remotehost bereitgestellt: einer OCI Compute-Instanz mit Oracle Linux 8, 4 CPU und 32 GB Arbeitsspeicher.
Die Desktopumgebung wird angezeigt, bevor der Remotehost bereit ist. Dieser Vorgang kann bis zu zwei Minuten dauern.
Visual Studio Code (VS Code) wird geöffnet und stellt automatisch eine Verbindung zur VM-Instanz her, die für Sie bereitgestellt wurde. Klicken Sie auf Weiter, um den Rechnerfingerprint zu akzeptieren.
Wenn Sie nicht auf Weiter klicken, wird im VS-Code ein unten dargestelltes Dialogfeld angezeigt. Klicken Sie auf Wiederholen. VS Code fordert Sie auf, den Fingerabdruck der Maschine zu akzeptieren. Klicken Sie anschließend auf Weiter.
Probleme beim Verbinden mit der Remote-Entwicklungsumgebung
Wenn andere Probleme auftreten, bei denen VS Code keine Verbindung zur Remote-Entwicklungsumgebung herstellt, die oben nicht behandelt werden, versuchen Sie Folgendes:
- VS-Code schließen
- Doppelklicken Sie auf dem Desktop auf das Symbol "Luna-Lab.html".
- Kopieren Sie das "Configure Script" aus der Registerkarte Resources, und fügen Sie es wieder in das Luna Desktop Terminal ein
- Wiederholen Sie die obigen Anweisungen, um eine Verbindung zur Remote-Entwicklungsumgebung herzustellen
Herzlichen Glückwunsch! Sie sind jetzt mit einem Remotehost in Oracle Cloud verbunden!
Das Skript öffnet den VS-Code, der mit Ihrem Remotehost verbunden ist und den Quellcode für die Übung geöffnet hat.
Öffnen Sie als Nächstes ein Terminal innerhalb des VS-Codes. Mit dem Terminal können Sie mit dem Remotehost interagieren. Ein Terminal kann in VS Code über das Menü geöffnet werden: Terminal > New Terminal, wie unten dargestellt.
Hinweis zur Entwicklungsumgebung
Sie verwenden GraalVM Enterprise als Java-Laufzeitumgebung für diese Übung. GraalVM ist eine leistungsstarke JDK-Distribution von Oracle, die auf Oracle Java SE basiert.
Ihre Entwicklungsumgebung ist mit GraalVM Enterprise und den für diese Übung erforderlichen Tools für Native Image vorkonfiguriert. Sie können dies prüfen, indem Sie die folgenden Befehle im Terminal ausführen:
java -version
native-image --version
Sie können mit dem nächsten Schritt fortfahren.
Schritt 2: JMH-Benchmark auf JVM kompilieren und ausführen
Der Quellcode für die Anwendung - JMH-Benchmark - ist auf Ihrem Remotehost verfügbar. Die JMH-Benchmark stammt aus dem Computer Language Benchmarks Game. Es werden Binärbäume erstellt - bevor Baumknoten Garbage-Sammlungen unterliegen. Dabei wird die Anzahl der Zuweisungen mindestens verwendet.
Diese JMH-Benchmark verwendet Java-Reflection. Das Tool native-image
arbeitet unter der so genannten "geschlossenen Welt"-Annahme und enthält keine reflektierend aufgerufenen Elemente in der nativen ausführbaren Datei, es sei denn, das Tool wird zum Zeitpunkt der Erstellung mit der erforderlichen Konfiguration bereitgestellt. Um eine native ausführbare Datei dieser JMH-Benchmark zu erstellen, müssen Sie den Tracing Agent ausführen, um die Reflexionskonfiguration native-image
bereitzustellen. Dies ist bereits geschehen, damit Sie Zeit sparen können. Die generierte Konfiguration finden Sie unter src/main/resources/META-INF/native-image/. Weitere Informationen zur Reflexionskonfiguration finden Sie unter Luna Lab on GraalVM Native Image and Reflection.
Erstellen Sie die Benchmark, und führen Sie sie dann als Java-Anwendung aus. Führen Sie dazu den folgenden Befehl aus:
mvn clean package exec:exec
Beachten Sie, dass in der Datei pom.xml Anweisungen vorhanden sind, den JIT-Compiler GraalVM mit der Option -XX:-UseJVMCICompiler
explizit zu deaktivieren. Das bedeutet, dass die Benchmark mit dem JIT-Compiler C2 ausgeführt wird.
Die Anwendung führt die Benchmark in drei Iterationen aus und zeigt die Ergebnisse im Terminal an. Die Ausführung sollte weniger als vier Minuten in Anspruch nehmen. Das Endergebnis ist das wichtigste. Es sollte Folgendes angezeigt werden:
Benchmark (binaryTreesN) Mode Cnt Score Error Units
BinaryTrees.bench 14 thrpt 3 180.819 ± 8.301 ops/s
Sie können jetzt mit dem nächsten Schritt fortfahren.
Schritt 3: JMH-Benchmark als native ausführbare Datei erstellen und ausführen
Erstellen Sie jetzt eine native ausführbare Datei mit GraalVM Enterprise Native Image.
Die JMH-Benchmark wird mit Maven erstellt und wendet das Maven-Plug-in für das Erstellen von nativen Images GraalVM an (öffnen Sie pom.xml, um die Registrierung des Plug-ins native-maven-plugin
anzuzeigen). Das Plug-in legt fest, welche JAR-Datei an native-image
übergeben werden muss und welche ausführbare Hauptklasse verwendet werden soll.
-
Erstellen Sie eine native ausführbare Datei. Der Build sollte etwa eine Minute dauern:
mvn package -Pnative
Das Maven-Profil
-Pnative
aktiviert die Erstellung einer nativen ausführbaren Datei. Er generiert eine native ausführbare Datei im target-Verzeichnis namensbenchmark-binary-tree
. -
Führen Sie dann die Benchmark als native ausführbare Datei aus:
./target/benchmark-binary-tree
Dies sind die Ergebnisse, die mit GraalVM Enterprise Native Image 22.2.0 erhalten wurden:
Benchmark (binaryTreesN) Mode Cnt Score Error Units BinaryTrees.bench 14 thrpt 3 174.135 ± 10.020 ops/s
Die nativen ausführbaren Zahlen können ähnlich oder besser als die vorherige (nicht native) Option sein. Die Ergebnisse variieren je nach Hardware, auf der Sie denselben Benchmark ausführen.
Sie können jetzt mit dem nächsten Schritt fortfahren.
SCHRITT 4: Natives Ausführbares Programm mit PGO und Run optimieren
Optimieren Sie jetzt Ihre native ausführbare Datei mit Profile-Guided Optimization (PGO). Es handelt sich um einen zweistufigen Prozess. Erstellen Sie zunächst eine instrumentierte Version der nativen ausführbaren Datei, und führen Sie sie aus, um ihre Ausführung zu verfolgen und ein Performanceprofil zu erfassen. Nach Abschluss der Ausführung wird eine Profildatei, default.iprof, im Root-Verzeichnis des Projekts generiert. Erstellen Sie dann eine optimierte ausführbare Datei mit den Profildaten zur Benchmark, und führen Sie sie aus.
Das Feature "Profil - Geführte Optimierung" (PGO) ist mit GraalVM Enterprise Edition verfügbar.
-
Erstellen Sie eine instrumentierte native ausführbare Datei, indem Sie das Maven-Profil
-Pinstrumented
übergeben:mvn package -Pinstrumented
Sie generiert eine Binärdatei im target-Verzeichnis namens
benchmark-binary-tree-instr
. -
Führen Sie den Prozess aus, um die Code-Ausführungsfrequenzprofile zu erfassen:
./target/benchmark-binary-tree-instr
Aus dieser Ausführung erfasste Profile werden in der Datei default.iprof im aktuellen Arbeitsverzeichnis gespeichert, sofern nichts anderes angegeben ist.
Hinweis: Sie können angeben, wo die Profile bei der Ausführung einer instrumentierten nativen ausführbaren Datei erfasst werden sollen, indem Sie die Option
-XX:ProfilesDumpFile=YourFileName
zur Laufzeit übergeben. Sie können auch mehrere Profildateien erfassen, indem Sie unterschiedliche Namen angeben und sie zur Erstellungszeit an das Toolnative-image
übergeben. -
Nachdem Sie die Profildatei generiert haben, erstellen Sie die optimierte Version:
mvn package -Poptimized
Er generiert eine optimierte Binärdatei im Verzeichnis
target
mit dem Namenbenchmark-binary-tree-opt
. -
Führen Sie abschließend die optimierte native ausführbare Datei aus:
./target/benchmark-binary-tree-opt
Dies sind die Ergebnisse, die mit GraalVM Enterprise Native Image 22.2.0 auf dem Hostrechner abgerufen werden:
Benchmark (binaryTreesN) Mode Cnt Score Error Units
BinaryTrees.bench 14 thrpt 3 223.241 ± 3.578 ops/s
Die durchschnittliche Anzahl von Vorgängen pro Sekunde stieg von 180, die als Java-Anwendung ausgeführt werden, auf 223, die als optimierte native ausführbare Datei ausgeführt werden. Die Ergebnisse variieren je nach Hardware, auf der Sie denselben Benchmark ausführen.
Übersicht
In dieser Übung haben Sie gezeigt, wie Sie native ausführbare Dateien mit Profile-Guided Optimization (PGO) optimieren können, um einen höheren Durchsatz im Vergleich zur Java-Version zu erzielen und gleichzeitig andere Vorteile zu erhalten: sofortiges Hochfahren, geringere CPU- und Speicherauslastung. Mit PGO können Sie Ihre Anwendung für bestimmte Workloads "trainieren" und in eine optimierte Binärdatei umwandeln, ohne die Performance zu beeinträchtigen.
Weitere Informationen
Glückwunsch. Sie haben diese Übung erfolgreich abgeschlossen.
Weitere Lernressourcen
Sehen Sie sich andere Übungen zu docs.oracle.com/learn an, oder greifen Sie auf weitere kostenlose Lerninhalte im Oracle Learning YouTube-Kanal zu. Besuchen Sie außerdem die Website education.oracle.com/learning-explorer, um Oracle Learning Explorer zu werden.
Produktdokumentation finden Sie im Oracle Help Center.
Optimize Cloud Native Java Applications with GraalVM Enterprise PGO
F75977-01
January 2023
Copyright © 2023, Oracle and/or its affiliates.