Hinweis:

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:

Hinweis: Oracle Cloud Infrastructure (OCI) stellt GraalVM Enterprise ohne zusätzliche Kosten bereit.

Übungsziele

In dieser Übung führen Sie folgende Schritte aus:

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.

VS-Code 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.

VS-Code - Verbindung wiederholen

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:

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.

VS-Code-Terminal

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.

  1. 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 namens benchmark-binary-tree.

  2. 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.

  1. 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.

  2. 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 Tool native-image übergeben.

  3. 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 Namen benchmark-binary-tree-opt.

  4. 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.