Eliminierung toten Codes vermeiden
Blackhole und State
Eliminierung toten Codes vermeiden ist eine kostenlose Java Academy-Lektion auf CoddyKit. Dies ist Lektion 4 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des Java Academy-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der Java Academy-Kurs umfasst insgesamt 4 Lektionen.
Dead-Code-Eliminierung vermeiden
Die größte Falle bei Microbenchmarks ist die Dead-Code-Eliminierung (DCE): Wenn der JIT beweisen kann, dass ein Ergebnis nie verwendet wird, entfernt er die Berechnung. Ihr Benchmark misst dann nichts. JMH bietet Ihnen zwei Werkzeuge, um dies zu verhindern — die Rückgabe von Werten und den Blackhole.
Die DCE-Falle
Diese Schleife berechnet eine Million Mal eine Quadratwurzel, verwendet das Ergebnis aber nie. Ein intelligenter Compiler kann die gesamte Schleife entfernen.
public class Main {
public static void main(String[] args) {
long t = System.nanoTime();
for (int i = 0; i < 1_000_000; i++) {
double ignored = Math.sqrt(i); // result thrown away
}
System.out.println("ns: " + (System.nanoTime() - t));
}
}Lösung 1: Das Ergebnis zurückgeben
Die einfachste Gegenmaßnahme besteht darin, den berechneten Wert aus der @Benchmark-Methode zurückzugeben. JMH verarbeitet jeden zurückgegebenen Wert, sodass die JVM nicht beweisen kann, dass er ungenutzt ist.
import org.openjdk.jmh.annotations.Benchmark;
public class Bench {
@Benchmark
public double sqrt() {
return Math.sqrt(42.0); // returned -> consumed by JMH
}
}Lösung 2: Der Blackhole
Wenn ein Benchmark mehrere Werte erzeugt oder Sie keinen Wert zurückgeben können, injizieren Sie einen Blackhole und rufen Sie consume(...) auf. Der Blackhole überzeugt den JIT davon, dass jeder Wert verwendet wird, ohne den Aufwand einer tatsächlichen Verarbeitung.
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.infra.Blackhole;
public class Bench {
@Benchmark
public void manyValues(Blackhole bh) {
for (int i = 0; i < 100; i++) {
bh.consume(Math.sqrt(i));
}
}
}@State-Objekte
Eine @State-Klasse enthält Eingaben, die für den Optimierer undurchsichtig sind, und verhindert dadurch Constant Folding. JMH instanziiert die Klasse und übergibt sie an Ihren Benchmark. Der Gültigkeitsbereich kann Thread, Benchmark (gemeinsam verwendet) oder Group sein.
import org.openjdk.jmh.annotations.*;
public class Bench {
@State(Scope.Thread)
public static class Data {
public int x = 21;
}
@Benchmark
public int multiply(Data d) {
return d.x * 2; // d.x is not a compile-time constant
}
}@Setup und @TearDown
Innerhalb einer @State-Klasse werden mit @Setup annotierte Methoden vor der Messung und mit @TearDown annotierte Methoden danach ausgeführt. Level steuert die Häufigkeit: Trial (einmal), Iteration oder Invocation.
import org.openjdk.jmh.annotations.*;
@State(Scope.Thread)
public class Data {
int[] arr;
@Setup(Level.Trial)
public void init() {
arr = new int[1000];
for (int i = 0; i < arr.length; i++) arr[i] = i;
}
}Konstante Eingaben vermeiden
Geben Sie der zu testenden Methode niemals Literalkonstanten. Math.sqrt(2.0) kann zu einer Konstante gefaltet werden; Math.sqrt(state.value) hingegen nicht. Beziehen Sie Eingaben immer aus einem @State-Feld.
Mehrere Werte zurückgeben
Wenn Ihr Benchmark auf natürliche Weise zwei Ergebnisse erzeugt, können Sie eines zurückgeben und das andere über einen Blackhole verbrauchen oder beide kombinieren. Wenn eines davon unverbraucht bleibt, entsteht erneut eine DCE-Lücke.
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.infra.Blackhole;
public class Bench {
@Benchmark
public int twoResults(Blackhole bh) {
int a = 3 * 7;
int b = 5 + 9;
bh.consume(b);
return a;
}
}Blackhole-Overhead
Der Blackhole ist auf äußerst geringe Kosten ausgelegt und selbst gegen Optimierungen geschützt, aber nicht völlig kostenlos. Bevorzugen Sie bei ultraschnellen Operationen die Rückgabe eines einzelnen Werts und verwenden Sie Blackhole für Schleifen und Fälle mit mehreren Werten.
Messwerte auf Plausibilität prüfen
Wenn ein Benchmark eine unrealistisch kurze Zeit meldet (für echte Arbeit weniger als eine Nanosekunde), sollten Sie DCE oder Constant Folding vermuten. Prüfen Sie erneut, ob Ergebnisse zurückgegeben oder verbraucht werden und ob die Eingaben aus @State stammen.
Alles zusammenführen
Ein robuster Benchmark liest Eingaben aus einem @State-Objekt, führt die Arbeit aus und gibt das Ergebnis entweder mit return zurück oder verbraucht es mit Blackhole.consume. Mit diesen drei Gewohnheiten können DCE und Constant Folding Ihre Messungen nicht verfälschen.
Kurzer Test
Testen Sie Ihr Verständnis dafür, wie sich die Eliminierung toten Codes verhindern lässt.
Zusammenfassung
Sie haben gelernt, Benchmarks zuverlässig zu halten:
- Eliminierung toten Codes entfernt nicht verwendete Berechnungen.
- Geben Sie ein einzelnes Ergebnis mit return zurück, damit JMH es verbraucht.
- Verwenden Sie Blackhole.consume für Schleifen und mehrere Werte.
- @State-Objekte halten Eingaben undurchsichtig und verhindern Constant Folding.
- @Setup / @TearDown bereiten den Zustand auf einem gewählten Level vor und räumen ihn auf.
Häufig gestellte Fragen
Ist die Lektion „Eliminierung toten Codes vermeiden“ kostenlos?
Ja — der vollständige Text von „Eliminierung toten Codes vermeiden“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des Java Academy-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der Java Academy-Kurs umfasst insgesamt 4 Lektionen.
Was lerne ich in „Eliminierung toten Codes vermeiden“?
Blackhole und State Du übst Java Academy mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.
Brauche ich Erfahrung, um Java Academy zu starten?
Keine Vorkenntnisse erforderlich. Java Academy auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 4 von 4.
Wie lange dauert die Lektion „Eliminierung toten Codes vermeiden“?
Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.
Kann ich in dieser Java Academy-Lektion Code schreiben und ausführen?
Ja. Jede Java Academy-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.
Alle Lektionen in diesem Kurs
- Warum JMH
- Einen Benchmark schreiben
- Aufwärmen und Iterationen
- Eliminierung toten Codes vermeiden