Java >> Java tutorial >  >> JVM

Hvor lang tid tager det for jvm at udføre escape-analyse? Måske længere end du tror.

Dette indlæg ser på escape-analyse, især hvor lang tid det tager for jvm at udføre escape-analyse i et kørende program. Jeg gør nogle observationer, men har ikke hele forklaringen på nuværende tidspunkt.

Lad os som introduktion tage en omvej for at se på et lidt kendt og endnu mindre brugt flag (som vi vil se er en god ting) i jvm, -Xcomp .

Funktionen for dette flag er defineret i jvm-dokumentationen som:

-Xcomp Tvinger kompilering af metoder ved første påkaldelse. Som standard er Client VM (-client ) udfører 1.000 fortolkede metodekald og server-VM'en (-server ) udfører 10.000 fortolkede metodeankaldelser for at indsamle information til effektiv kompilering. Angivelse af -Xcomp option deaktiverer fortolkede metodeankaldelser for at øge kompileringsydelsen på bekostning af effektiviteten.

Ved første øjekast ser dette ud til at være en glimrende mulighed. En genvej til opvarmning af jvm gennem 10.000 cyklusser – vi kan få koden til at kompilere med det samme. Bør vi ikke altid aktivere denne mulighed som standard?

Men dokumentationen advarer om, at dette vil være 'på bekostning af effektivitet'.

Jvm'en lærer om kodeadfærd i de 10.000 opvarmningscyklusser, så den kompilerer på den mest effektive måde, når det kommer til kompilering. At kompilere koden med det samme vil betyde, at ja, koden er faktisk kompileret, men at den kompilerede kode måske ikke er den mest effektive. Du kan læse mere om det i dette blogindlæg - men det er egentlig ikke emnet for dette indlæg.

Noget andet, der ikke sker, hvis du bruger -Xcomp, er escape-analyse. Dette er faktisk ret overraskende, da jvm'en ikke burde lære om, hvorvidt escape-analyse er mulig ved at køre programmet. Dette bør fremgå af en statisk analyse af koden.

Tag et kig på denne kode (jeg blev inspireret af ideerne i denne blog):

import java.io.IOException;
import java.util.Optional;

/**
 * Created by daniel on 17/12/2015.
 */
public class Test {
    private static String NAME;

    public static void main(String[] args)throws IOException {
        new Test().test();
    }
    public void test() throws IOException {

        Name name = new Name("Steven");
        int iterations = 1_000_000;

        for(;;){
            countOptional(name, iterations);
            System.out.println("Press any key to continue");
            System.in.read();
        }
    }

    private static void countOptional(Name name, int iterations) {
        for (int i = 0; i < iterations; i++) {
            NAME = name.getOptionalName().get();
        }
        System.out.println(iterations + " optional iterations " + NAME);
    }
    
    class Name {
        private final String name;

        public Name(String name) {
            this.name = name;
        }

        public Optional<String> getOptionalName() {
            return Optional.ofNullable(name);
        }
    }
}

Vi skal sikre os, at programmet kører uden en gc (jeg foreslår disse flag):

-verbosegc -Xmx4g -Xms4g

Når programmet venter på input, udfør en heap-dump for at se hvor mange Optional objekt er blevet oprettet. Tryk derefter på en vilkårlig tast for at genoptage programmet.

For at udføre en heap-dump skal du først køre jps for at identificere programmets pid, kør derefter:

jmap -histo pid | head

Gør dette én gang uden -Xcomp-flaget og én gang med -Xcomp-flaget.

Uden -Xcomp-flaget

Efter første iteration:

Efter anden iteration:

Alle efterfølgende iterationer er de samme, ingen yderligere objekter oprettes:

Der er tydeligvis escape-analyse i gang efter 234.000 iterationer - ved ikke hvorfor det skulle tage så lang tid, normalt (for eksempel med kompilering af kode) er 10k iterationer nok? Også i den anden iteration skaber den yderligere ~400.000 objekter før escape analyse kick ind, hvilket også er en smule mystisk.

Med -Xcomp-flaget

Efter den første iteration:

Efter anden iteration:

Efter hver iteration antallet af Optional genstande stiger 1m.

Oversigt

  • -Xcomp er en switch, der næsten helt sikkert aldrig bør bruges i produktionen. Jeg kan forestille mig nogle scenarier, hvor du måske vil lege med at deaktivere tolken, men det ville være meget specifikke edge cases.
  • Det ser ud til at tage mindst 200K iteration, før escape-analyse er effektiv. Så du skal tillade længere end de 10.000 iterationer for en fuld opvarmning.
  • Der er også en anden fase, hvor det ser ud til at være nødvendigt at gøre dette igen efter at have undslippet objekter. Dette kræver yderligere forståelse.
  • Hvis du sænker programmet en smule ved at gøre noget arbejde mellem opkaldene for at oprette det valgfrie, reduceres antallet af objekter. For eksempel fandt jeg ud af, at et kald til Math.sin reducerer de valgfrie objekter med ca. 50 %.

Java tag