Undgå dead-code elimination
Blackhole og state
Undgå dead-code elimination er en gratis Java Academy-lektion på CoddyKit. Dette er lektion 4 af 4. Du kan læse hele lektionen gratis nedenfor — og derefter øve dig praktisk i browseren med en indbygget kodeeditor og en AI-vejleder, der er tilgængelig døgnet rundt. Den er en del af læringsforløbet i Java Academy, og dine fremskridt synkroniseres på tværs af nettet og CoddyKit-appen. Java Academy-kurset indeholder 4 lektioner i alt.
Undgå eliminering af død kode
Den største faldgrube ved mikrobenchmarking er eliminering af død kode (DCE): Hvis JIT kan bevise, at et resultat aldrig bruges, sletter den beregningen. Dit benchmark måler så ingenting. JMH giver dig to værktøjer til at forhindre dette — returværdier og Blackhole.
DCE-fælden
Denne løkke beregner en kvadratrod en million gange, men bruger aldrig resultatet. En intelligent compiler kan slette hele løkken.
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øsning 1: Returnér resultatet
Det enkleste forsvar er at returnere den beregnede værdi fra @Benchmark-metoden. JMH bruger alle returnerede værdier, så JVM kan ikke bevise, at de er døde.
import org.openjdk.jmh.annotations.Benchmark;
public class Bench {
@Benchmark
public double sqrt() {
return Math.sqrt(42.0); // returned -> consumed by JMH
}
}Løsning 2: Blackhole
Når et benchmark producerer flere værdier, eller du ikke kan returnere én, skal du indsætte en Blackhole og kalde consume(...). Blackhole overbeviser JIT om, at hver værdi bruges, uden omkostningen ved faktisk arbejde.
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-objekter
En @State-klasse indeholder input, der er uigennemsigtige for optimeringsværktøjet, og dermed forhindrer konstantfoldning. JMH opretter en instans af den og sender den til dit benchmark. Omfanget kan være Thread, Benchmark (delt) eller Group.
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 og @TearDown
I en @State-klasse kører metoder, der er annoteret med @Setup, før målingen, og @TearDown efter den. Level styrer hyppigheden: Trial (én gang), Iteration eller 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;
}
}Undgå konstante input
Tilfør aldrig bogstavelige konstanter til den metode, der testes. Math.sqrt(2.0) kan foldes til en konstant, mens Math.sqrt(state.value) ikke kan. Hent altid input fra et @State-felt.
Returnering af flere værdier
Hvis dit benchmark naturligt producerer to resultater, kan du returnere det ene og forbruge det andet via en Blackhole eller kombinere dem. Hvis et af dem ikke forbruges, åbner du igen for DCE-hullet.
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;
}
}Omkostninger ved Blackhole
Blackhole er designet til at være ekstremt billig og selv modstandsdygtig over for optimering, men den er ikke helt gratis. Ved ultrahurtige operationer bør du foretrække at returnere en enkelt værdi og bruge Blackhole til løkker og tilfælde med flere værdier.
Kontrollér dine tal
Hvis et benchmark rapporterer en umuligt lav tid (under et nanosekund for reelt arbejde), så mistænk DCE eller konstantfoldning. Kontrollér igen, at resultater returneres eller forbruges, og at input kommer fra @State.
Sæt det hele sammen
Et robust benchmark læser input fra et @State-objekt, udfører arbejdet og enten returnerer resultatet eller forbruger det med Blackhole.consume. Med disse tre vaner kan DCE og konstantfoldning ikke forvrænge dine målinger.
Hurtig kontrol
Kontrollér din forståelse af, hvordan eliminering af død kode forhindres.
Opsummering
Du har lært at holde benchmarks ærlige:
- Eliminering af død kode sletter ubrugte beregninger.
- Returnér et enkelt resultat, så JMH kan forbruge det.
- Brug Blackhole.consume til løkker og flere værdier.
- @State-objekter holder input skjult og forhindrer konstantfoldning.
- @Setup / @TearDown forbereder og rydder op i tilstanden på et valgt Level.
Lær Java med en AI-underviser — gratis
Skriv og kør rigtig kode i din browser, få øjeblikkelig hjælp fra en AI-underviser døgnet rundt, og fortsæt, hvor du slap, på web eller i appen.
- Kurser
- 104
- Lektioner
- 374
Ofte stillede spørgsmål
Er lektionen “Undgå dead-code elimination” gratis?
Ja — hele teksten til “Undgå dead-code elimination” kan læses gratis her på nettet. Hvis du vil øve dig interaktivt med en indbygget kodeeditor og en AI-vejleder døgnet rundt og få adgang til resten af Java Academy-kurset, skal du opgradere til CoddyKit PRO. Java Academy-kurset indeholder 4 lektioner i alt.
Hvad lærer jeg i “Undgå dead-code elimination”?
Blackhole og state Du øver dig i Java Academy med praktisk kode, som du kører direkte i browseren, og en AI-vejleder døgnet rundt besvarer dine spørgsmål, mens du arbejder dig gennem lektionen.
Skal jeg have erfaring for at begynde på Java Academy?
Der kræves ingen tidligere erfaring. Java Academy på CoddyKit er tilrettelagt for både begyndere og øvede, så du kan starte her eller fra begyndelsen og lære i dit eget tempo. Dette er lektion 4 af 4.
Hvor lang tid tager lektionen “Undgå dead-code elimination”?
De fleste CoddyKit-lektioner tager cirka 5–10 minutter. Hver lektion er kort og interaktiv, så du gør løbende fremskridt og kan fortsætte, hvor du slap – på både web og app.
Kan jeg skrive og køre kode i denne Java Academy-lektion?
Ja. Alle Java Academy-lektioner har en indbygget kodeeditor, så du kan skrive og køre rigtig kode direkte i din browser og få øjeblikkelig feedback fra AI – uden lokal opsætning.
Alle lektioner i dette kursus
- Hvorfor JMH
- Skriv et benchmark
- Warmup og iterationer
- Undgå dead-code elimination