Java Academy · Lektion

Hvorfor JMH

Undgå naive fejl ved benchmarks

Lektion 1 af 413 trin

Hvorfor JMH er en gratis Java Academy-lektion på CoddyKit. Dette er lektion 1 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.

Hvorfor JMH

Java Microbenchmark Harness (JMH) er standardværktøjet til at måle ydeevnen for små stykker Java-kode. Hjemmelavede tidsmålingsløkker giver næsten altid forkerte tal, fordi JVM er et avanceret optimerende køretidsmiljø.

JMH findes for at neutralisere disse faldgruber.

Det naive benchmark

Et typisk første forsøg pakker en løkke ind i System.nanoTime(). Det ser rimeligt ud, men er grundlæggende fejlbehæftet til mikrobenchmarks.

public class Main {
    static int compute(int n) { return n * n + 7; }
    public static void main(String[] args) {
        long start = System.nanoTime();
        int sink = 0;
        for (int i = 0; i < 1_000_000; i++) sink = compute(i);
        long elapsed = System.nanoTime() - start;
        System.out.println("ns: " + elapsed + " sink=" + sink);
    }
}

Problem 1: JIT-opvarmning

JVM starter i fortolket tilstand og kompilerer først varme metoder til maskinkode efter tusindvis af kald. Et naivt benchmark måler den langsomme fortolkede fase blandet med den hurtige kompilerede fase, hvilket giver meningsløse gennemsnit.

JMH løser dette med en dedikeret opvarmningsfase, som kasseres.

Problem 2: Eliminering af død kode

Hvis et beregnet resultat aldrig bruges, kan JIT slette beregningen helt. Dit benchmark måler så en tom løkke.

JMH stiller brug af returværdier og Blackhole til rådighed for at forhindre dette.

Problem 3: Konstantfoldning

Hvis input er konstanter, der er kendt ved kompilering, beregner JIT svaret én gang og genbruger det. I eksemplet nedenfor kunne compileren erstatte hele løkken med én konstant.

JMH bruger @State-objekter, så input er uigennemsigtige for optimeringsværktøjet.

public class Main {
    public static void main(String[] args) {
        // 2 * 21 is constant; the JIT folds it to 42
        int result = 2 * 21;
        System.out.println(result);
    }
}

Problem 4: Løkkeoptimeringer

JIT udfolder løkker, flytter invariant kode ud af dem og vektoriserer operationer. En håndskrevet løkke måler disse optimeringer i stedet for den operation, du havde til hensigt at teste.

JMH erstatter din løkke med omhyggeligt kontrollerede iterationsantal, som det selv administrerer.

Problem 5: Udskiftning på stakken

En langvarig løkke i main kan kompileres midt under kørslen (udskiftning på stakken), hvilket giver andre ydeevneegenskaber end en normalt kompileret metode. Det skævvrider resultaterne uforudsigeligt.

Det leverer JMH

  • Separate, kasserede opvarmnings-iterationer.
  • Flere måle-iterationer med statistik.
  • Forgrening til nye JVM'er for at undgå profilforurening.
  • Blackhole og brug af resultater for at forhindre eliminering af død kode.
  • @State-objekter for at forhindre konstantfoldning.

Sådan kører du det

JMH er en separat afhængighed (org.openjdk.jmh) og startes normalt af en annotationsprocessor samt et Maven/Gradle-build, der opretter en eksekverbar JAR-fil. Du kører ikke benchmarks fra en almindelig main som almindelig kode.

Statistik er vigtig

JMH rapporterer ikke kun et gennemsnit, men også fejlen / konfidensintervallet på tværs af iterationer og forgreninger. Et resultat på 42.0 +/- 1.3 ns/op fortæller dig både den centrale værdi og hvor meget den varierede — hvilket er afgørende for at kunne stole på en måling.

Hvornår skal du bruge JMH

Brug JMH, når du sammenligner to implementationer af en varm kodevej, validerer en optimering eller måler operationer fra nanosekund- til mikrosekundsskala. Til groft arbejde på sekundskala, f.eks. I/O og netværk, er måling af den faktiske tid normalt tilstrækkelig.

Hurtigt tjek

Test din forståelse af, hvorfor JMH er nødvendigt.

Opsummering

Du har lært, hvorfor mikrobenchmarking kræver et harness:

  • JVM varmer op: Fortolket kode bliver først kompileret efter mange kald.
  • Eliminering af død kode og konstantfoldning kan slette eller forudberegne dit arbejde.
  • Løkkeoptimeringer og udskiftning på stakken forvrider håndskrevne løkker.
  • JMH tilføjer opvarmning, måle-iterationer, forgrening, Blackhole og statistik.
  • Brug det, når du måler varme kodeveje på nanosekundskala.
Gratis at komme i gang

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 “Hvorfor JMH” gratis?

Ja — hele teksten til “Hvorfor JMH” 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 “Hvorfor JMH”?

Undgå naive fejl ved benchmarks 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 1 af 4.

Hvor lang tid tager lektionen “Hvorfor JMH”?

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

  1. Hvorfor JMH
  2. Skriv et benchmark
  3. Warmup og iterationer
  4. Undgå dead-code elimination
← Tilbage til Java Academy