Metode Inline i JVM

1. Introduksjon

I denne opplæringen tar vi en titt på hvilken metode som er innebygd i Java Virtual Machine og hvordan den fungerer.

Vi vil også se hvordan vi kan få og lese informasjonen knyttet til inline fra JVM og hva vi kan gjøre med denne informasjonen for å optimalisere koden vår.

2. Hvilken metode er det?

I utgangspunktet, inlining er en måte å optimalisere kompilert kildekode ved kjøretid ved å erstatte påkallingen av de ofte utførte metodene med kroppene.

Selv om det er kompilering involvert, blir det ikke utført av det tradisjonelle javac kompilator, men av selve JVM. For å være mer presis, det er ansvaret for Just-In-Time (JIT) kompilatoren, som er en del av JVM; javac produserer bare en bytekode og lar JIT gjøre magien og optimalisere kildekoden.

En av de viktigste konsekvensene av denne tilnærmingen er at hvis vi kompilerer koden ved hjelp av gammel Java, er det samme.klasse filen blir raskere på nyere JVM-er. På denne måten trenger vi ikke å kompilere kildekoden på nytt, men bare oppdatere Java.

3. Hvordan JIT gjør det?

I hovedsak er det JIT-kompilator prøver å integrere metodene vi ofte kaller, slik at vi kan unngå overhead av en metodeinnkallelse. Det tar to ting i betraktning når man bestemmer om man skal integrere en metode eller ikke.

For det første bruker den tellere for å holde rede på hvor mange ganger vi påkaller metoden. Når metoden kalles mer enn et bestemt antall ganger, blir den “varm”. Denne terskelen er satt til 10.000 som standard, men vi kan konfigurere den via JVM-flagget under Java-oppstart. Vi vil definitivt ikke integrere alt siden det ville være tidkrevende og ville produsere en enorm bytekode.

Vi bør huske på at innlining bare vil finne sted når vi kommer til en stabil tilstand. Dette betyr at vi må gjenta utførelsen flere ganger for å gi nok profilinformasjon for JIT-kompilatoren.

Videre kan det ikke være "varmt" at garantien er at metoden vil være inline. Hvis den er for stor, vil ikke JIT legge den inn. Den akseptable størrelsen er begrenset av -XX: FreqInlineSize = flagg, som spesifiserer maksimalt antall instruksjoner for bytekode for å legge inn en metode.

Det er likevel sterkt anbefalt å ikke endre standardverdien til dette flagget med mindre vi er helt sikre på å vite hvilken innvirkning det kan ha. Standardverdien avhenger av plattformen - for 64-bit Linux er den 325.

JIT inlines statisk, privat, eller endelig metoder generelt. Og mens offentlig metoder er også kandidater for inlineing, ikke alle offentlige metoder vil nødvendigvis være inline. JVM må bestemme at det bare er en enkelt implementering av en slik metode. Enhver ekstra underklasse vil forhindre inline og ytelsen vil uunngåelig reduseres.

4. Finne varme metoder

Vi vil absolutt ikke gjette hva JIT gjør. Derfor trenger vi noen måte å se hvilke metoder som er innstilt eller ikke innstilt. Vi kan enkelt oppnå dette og logge all denne informasjonen til standardutgangen ved å sette noen ekstra JVM-flagg under oppstart:

-XX: + PrintCompilation -XX: + UnlockDiagnosticVMOptions -XX: + PrintInlining

Det første flagget logges når JIT-kompilering skjer. Det andre flagget muliggjør tilleggsflagg inkludert -XX: + PrintInlining, som vil skrive ut hvilke metoder som blir inline og hvor.

Dette vil vise oss de inline metodene i form av et tre. Bladene er merket og merket med ett av følgende alternativer:

  • inline (hot) - denne metoden er merket som varm og er inline
  • for stor - metoden er ikke varm, men også den genererte bykoden er for stor, så den er ikke inline
  • varm metode for stor - dette er en varm metode, men den er ikke inline siden bytekoden er for stor

Vi bør ta hensyn til den tredje verdien og prøve å optimalisere metodene med merkelappen “hot method too large”.

Generelt, hvis vi finner en varm metode med en veldig kompleks betinget uttalelse, bør vi prøve å skille innholdet i hvis-uttalelse og øke granulariteten slik at JIT kan optimalisere koden. Det samme gjelder for bytte om og til-løkkeuttalelser.

Vi kan konkludere med at manuell innlining er noe vi ikke trenger å gjøre for å optimalisere koden vår. JVM gjør det mer effektivt, og vi vil muligens gjøre koden lang og vanskelig å følge.

4.1. Eksempel

La oss nå se hvordan vi kan sjekke dette i praksis. Vi oppretter først en enkel klasse som beregner summen av den første N sammenhengende positive heltall:

offentlig klasse ConsecutiveNumbersSum {private long totalSum; private int totalNumbers; public ConsecutiveNumbersSum (int totalNumbers) {this.totalNumbers = totalNumbers; } offentlig lang getTotalSum () {totalSum = 0; for (int i = 0; i <totalNumbers; i ++) {totalSum + = i; } returnere totalSum; }}

Deretter vil en enkel metode bruke klassen til å utføre beregningen:

privat statisk lang beregneSum (int n) {returner nye KonsekvensNumreSum (n) .getTotalSum (); }

Til slutt vil vi kalle metoden flere ganger og se hva som skjer:

for (int i = 1; i <NUMBERS_OF_ITERATIONS; i ++) {calcSum (i); }

I det første løpet vil vi kjøre det 1000 ganger (mindre enn terskelverdien på 10.000 nevnt ovenfor). Hvis vi søker i utdataene etter beregneSum () metoden, finner vi den ikke. Dette forventes siden vi ikke kalte det nok ganger.

Hvis vi nå endrer antall iterasjoner til 15.000 og søker i utdataene igjen, ser vi:

664 262% com.baeldung.inlining.InliningExample :: main @ 2 (21 bytes) @ 10 com.baeldung.inlining.InliningExample :: calcinSum (12 bytes) inline (hot)

Vi kan se at denne gangen oppfyller metoden vilkårene for inlining og JVM innrammet den.

Det er bemerkelsesverdig å nevne igjen at hvis metoden er for stor, vil JIT ikke integrere den, uavhengig av antall iterasjoner. Vi kan sjekke dette ved å legge til et nytt flagg når du kjører applikasjonen:

-XX: FreqInlineSize = 10

Som vi kan se i forrige utgang, er størrelsen på metoden vår 12 byte. De -XX:FreqInlineSize flagg vil begrense metodestørrelsen som er kvalifisert for inlining til 10 byte. Følgelig bør innleggingen ikke finne sted denne gangen. Og faktisk kan vi bekrefte dette ved å ta en titt på utgangen:

330 266% com.baeldung.inlining.InliningExample :: main @ 2 (21 bytes) @ 10 com.baeldung.inlining.InliningExample :: calcinSum (12 byte) varm metode for stor

Selv om vi har endret flaggverdien her for illustrasjonsformål, må vi understreke anbefalingen om ikke å endre standardverdien for -XX: FreqInlineSize flagg med mindre det er absolutt nødvendig.

5. Konklusjon

I denne artikkelen så vi hvilken metode inlining er i JVM og hvordan JIT gjør det. Vi beskrev hvordan vi kan sjekke om metodene våre er kvalifiserte for innføring eller ikke, og foreslo hvordan vi kan bruke denne informasjonen ved å prøve å redusere størrelsen på ofte kalte lange metoder som er for store til å bli inline.

Til slutt illustrerte vi hvordan vi kan identifisere en varm metode i praksis.

Alle kodebitene som er nevnt i artikkelen, finner du i GitHub-depotet vårt.