Vkladanie metód do JVM

1. Úvod

V tomto výučbe sa pozrieme na to, čo je metóda vloženia textu do Java Virtual Machine a ako funguje.

Uvidíme tiež, ako získať a prečítať informácie týkajúce sa vloženia z JVM a čo môžeme urobiť s týmito informáciami s cieľom optimalizovať náš kód.

2. Čo je metóda vloženia?

V podstate vloženie je spôsob, ako optimalizovať kompilovaný zdrojový kód za behu nahradením vyvolania najčastejšie vykonávaných metód jeho telami.

Aj keď je to spojené s kompiláciou, nevykonáva sa to tradične javac kompilátor, ale samotný JVM. Aby som bol presnejší, je to zodpovednosť kompilátora Just-In-Time (JIT), ktorá je súčasťou JVM; javac iba vyprodukuje bytecode a nechá JIT urobiť kúzlo a optimalizovať zdrojový kód.

Jedným z najdôležitejších dôsledkov tohto prístupu je, že ak kód kompilujeme pomocou starej Javy, to isté.trieda súbor bude rýchlejší na novších JVM. Takto nemusíme prekompilovať zdrojový kód, stačí iba aktualizovať jazyk Java.

3. Ako to robí JIT?

V podstate Kompilátor JIT sa snaží vložiť metódy, ktoré často voláme, aby sme sa vyhli réžii vyvolávania metód. Pri rozhodovaní, či vložiť metódu, alebo nie, berie do úvahy dve veci.

Najskôr pomocou počítadiel sleduje, koľkokrát metódu vyvoláme. Ak sa metóda volá viackrát ako špecificky, stáva sa „horúcou“. Táto hranica je predvolene nastavená na 10 000, môžeme ju však nakonfigurovať pomocou príznaku JVM počas spustenia Javy. Rozhodne nechceme vložiť všetko, pretože by to bolo časovo náročné a prinieslo by to obrovský bytecode.

Mali by sme mať na pamäti, že vloženie bude prebiehať, až keď sa dostaneme do stabilného stavu. To znamená, že vykonanie budeme musieť opakovať niekoľkokrát, aby sme poskytli dostatok profilovacích informácií pre kompilátor JIT.

Navyše, byť „horúci“ nezaručuje, že metóda bude podčiarknutá. Ak je príliš veľká, SVT to nezaradí. Prijateľná veľkosť je obmedzená -XX: FreqInlineSize = príznak, ktorý určuje maximálny počet inštrukcií bytecode, ktoré sa majú vložiť pre metódu.

Napriek tomu sa dôrazne odporúča nemeniť predvolenú hodnotu tohto príznaku, pokiaľ si nie sme úplne istí, aký bude jeho dopad. Predvolená hodnota závisí od platformy - pre 64-bitový Linux je to 325.

JIT podčiarkuje statický, súkromné, alebo konečné metódy všeobecne. A zatiaľ verejné metódy sú tiež kandidátmi na vloženie, nie každá verejná metóda bude nevyhnutne vložená. JVM musí určiť, že existuje iba jedna implementácia takejto metódy. Akákoľvek ďalšia podtrieda by zabránila vloženiu a výkon sa nevyhnutne zníži.

4. Hľadanie horúcich metód

Určite nechceme hádať, čo robí JIT. Preto potrebujeme nejaký spôsob, ako zistiť, ktoré metódy sú alebo nie sú vložené. Toho ľahko dosiahneme a všetky tieto informácie prihlásime na štandardný výstup nastavením niektorých ďalších príznakov JVM počas spustenia:

-XX: + Print Comppilation -XX: + UnlockDiagnosticVMOptions -XX: + PrintInlining

Prvý príznak sa zaznamená, keď dôjde ku kompilácii JIT. Druhý príznak umožňuje ďalšie príznaky vrátane -XX: + PrintInlining, ktorý vytlačí, aké metódy sa zaraďujú a kde.

Ukážeme nám vložené metódy vo forme stromu. Listy sú anotované a označené jednou z nasledujúcich možností:

  • vložený (horúci) - táto metóda je označená ako horúca a je podčiarknutá
  • príliš veľký - metóda nie je horúca, ale aj jej generovaný bytecode je príliš veľký, takže nie je podčiarknutý
  • horúca metóda príliš veľká - toto je horúca metóda, ale nie je podčiarknutá, pretože bytecode je príliš veľký

Mali by sme venovať pozornosť tretej hodnote a pokúsiť sa optimalizovať metódy s označením „horúca metóda je príliš veľká“.

Všeobecne platí, že ak nájdeme horúcu metódu s veľmi zložitým podmieneným príkazom, mali by sme sa pokúsiť oddeliť obsah keby-vyhlásenie a zvýšiť zrnitosť, aby mohol JIT optimalizovať kód. To isté platí pre prepínač a pre-slučkové vyhlásenia.

Môžeme dospieť k záveru, že vloženie manuálnej metódy je niečo, čo nemusíme robiť, aby sme optimalizovali náš kód. Spoločný podnik JVM to robí efektívnejšie a my by sme pravdepodobne vytvorili tento kód dlho a ťažko sledovateľný.

4.1. Príklad

Pozrime sa teraz, ako to môžeme skontrolovať v praxi. Najskôr vytvoríme jednoduchú triedu, ktorá vypočíta súčet prvej N po sebe idúce kladné celé čísla:

verejná trieda ConsecutiveNumbersSum {private long totalSum; private int totalNumbers; public ConsecutiveNumbersSum (int totalNumbers) {this.totalNumbers = totalNumbers; } verejné dlho getTotalSum () {totalSum = 0; pre (int i = 0; i <totalNumbers; i ++) {totalSum + = i; } návrat totalSum; }}

Ďalej bude na vykonanie výpočtu použitá trieda jednoduchou metódou:

private static long countSum (int n) {return new ConsequiveNumbersSum (n) .getTotalSum (); }

Nakoniec metódu zavoláme niekoľkokrát a uvidíme, čo sa stane:

pre (int i = 1; i <NUMBERS_OF_ITERATIONS; i ++) {CalcSum (i); }

V prvom spustení ho spustíme 1 000-krát (menej ako je prahová hodnota 10 000 uvedená vyššie). Ak budeme hľadať výstup pre vypočítaťSum () metóda, nenájdeme. Očakáva sa to, pretože sme to nevolali dosťkrát.

Ak teraz zmeníme počet iterácií na 15 000 a znova vyhľadáme výstup, uvidíme:

664 262% com.baeldung.inlining.InliningExample :: main @ 2 (21 bajtov) @ 10 com.baeldung.inlining.InliningExample :: CalcSum (12 bajtov) vložený (horúci)

Vidíme, že metóda tentoraz spĺňa podmienky pre vloženie a JVM to vložila.

Je potrebné spomenúť ešte raz, že ak je metóda príliš veľká, JIT ju nezaradí, bez ohľadu na počet iterácií. Môžeme to skontrolovať pridaním ďalšieho príznaku pri spustení aplikácie:

-XX: FreqInlineSize = 10

Ako vidíme v predchádzajúcom výstupe, veľkosť našej metódy je 12 bajtov. The -XX:FreqInlineSize príznak obmedzí veľkosť metódy vhodnej na vloženie na 10 bajtov. V dôsledku toho by sa vloženie nemalo tentokrát uskutočniť. Môžeme to potvrdiť ďalším pohľadom na výstup:

330 266% com.baeldung.inlining.InliningExample :: main @ 2 (21 bajtov) @ 10 com.baeldung.inlining.InliningExample :: CalcSum (12 bajtov) horúca metóda príliš veľká

Aj keď sme tu zmenili hodnotu príznaku na ilustračné účely, musíme zdôrazniť odporúčanie nezmeniť predvolenú hodnotu parametra -XX: FreqInlineSize ak to nie je nevyhnutne potrebné.

5. Záver

V tomto článku sme videli, aká metóda vloženia je v JVM a ako to robí JIT. Opísali sme, ako môžeme skontrolovať, či sú naše metódy vhodné na vloženie alebo nie, a navrhli sme, ako tieto informácie využiť tak, že sa pokúsime zmenšiť veľkosť často nazývaných dlhých metód, ktoré sú príliš veľké na to, aby sa dali vložiť.

Na záver sme ilustrovali, ako môžeme v praxi identifikovať horúcu metódu.

Všetky útržky kódu uvedené v článku nájdete v našom úložisku GitHub.