Módszer beillesztése a JVM-be

1. Bemutatkozás

Ebben az oktatóanyagban megvizsgáljuk, hogy a Java Virtual Machine milyen módszerrel rendelkezik és hogyan működik.

Meglátjuk azt is, hogyan szerezhetjük be és olvashatjuk el a beillesztéssel kapcsolatos információkat a JVM-ből, és mit tehetünk ezekkel az információkkal a kódunk optimalizálása érdekében.

2. Milyen módszer a vonalvezetés?

Alapvetően, Az inlining a fordított forráskód futás közbeni optimalizálásának egyik módja azáltal, hogy a leggyakrabban végrehajtott módszerek meghívásait testekkel helyettesíti.

Bár összeállítás is van benne, a hagyományos nem javac fordító, hanem maga a JVM. Precízebbnek lenni, ez a Just-In-Time (JIT) fordító felelőssége, amely a JVM része; javac csak bájtkódot állít elő, és lehetővé teszi a JIT számára a varázslatot és a forráskód optimalizálását.

Ennek a megközelítésnek az egyik legfontosabb következménye, hogy ha a kódot régi Java használatával állítjuk össze, ugyanaz.osztály a fájl gyorsabb lesz az újabb JVM-eken. Így nem kell újrafordítanunk a forráskódot, hanem csak a Java-t kell frissítenünk.

3. Hogyan működik a JIT?

Lényegében a A JIT fordító megpróbálja felvázolni azokat a módszereket, amelyeket gyakran hívunk, hogy elkerüljük a módszer meghívásának általános költségeit. Két dolgot vesz figyelembe, amikor eldönti, hogy beiktat-e egy módszert vagy sem.

Először számlálókkal követi nyomon, hogy hányszor hívjuk meg a módszert. Ha a módszert többször hívják meg, mint meghatározott számú alkalommal, akkor az „forróvá” válik. Ez a küszöb alapértelmezés szerint 10 000, de a Java indításakor a JVM zászlón keresztül konfigurálhatjuk. Határozottan nem akarunk mindent beilleszteni, mivel időigényes lenne és hatalmas byte-kódot produkálna.

Nem szabad megfeledkeznünk arról, hogy a beillesztésre csak akkor kerül sor, ha stabil állapotba kerülünk. Ez azt jelenti, hogy többször meg kell ismételnünk a végrehajtást, hogy elegendő profiladatot biztosítsunk a JIT fordító számára.

Továbbá az, hogy „meleg”, nem garantálja a módszer beillesztését. Ha túl nagy, a JIT nem vonja be. Az elfogadható méretet a -XX: FreqInlineSize = flag, amely meghatározza a metódusba beillesztendő bytecode utasítások maximális számát.

Mindazonáltal erősen ajánlott, hogy ne változtassa meg a jelző alapértelmezett értékét, hacsak nem vagyunk teljesen biztosak abban, hogy tudjuk, milyen hatást gyakorolhat. Az alapértelmezett érték a platformtól függ - 64 bites Linux esetén 325.

A közös nyomozócsoport meghatározza statikus, magán, vagy végső módszerek általában. És míg nyilvános módszerek is jelöltek a beágyazásra, nem minden nyilvános módszer kerül feltétlenül beillesztésre. A JVM-nek meg kell határoznia, hogy csak egy ilyen módszer valósítható meg. Bármely további alosztály megakadályozhatja a beillesztést, és a teljesítmény elkerülhetetlenül csökken.

4. Forró módszerek keresése

Biztosan nem akarjuk kitalálni, hogy a JIT mit csinál. Ezért valamilyen módszerre van szükségünk annak megtekintéséhez, hogy mely módszerek vannak beillesztve vagy nem. Könnyen elérhetjük ezt, és minden ilyen információt naplózhatunk a standard kimenetbe, ha néhány további JVM jelzőt állítunk be az indítás során:

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

Az első jelző naplózásra kerül, amikor a JIT összeállítása megtörténik. A második zászló további zászlókat tesz lehetővé, beleértve a -XX: + PrintInlining, amely kinyomtatja, hogy milyen módszerek kerülnek beillesztésre és hol.

Ez megmutatja nekünk a beágyazott módszereket fa formájában. A leveleket a következő lehetőségek egyikével jegyzik fel és jelölik:

  • sorban (forró) - ez a módszer forrónak van jelölve és be van vonva
  • túl nagy - a módszer nem forró, de a generált bájtkódja is túl nagy, ezért nincs beillesztve
  • forró módszer túl nagy - ez egy forró módszer, de nincs beillesztve, mivel a bájtkód túl nagy

Figyelnünk kell a harmadik értékre, és a „hot method too big” címkével próbálnánk optimalizálni a módszereket.

Általában, ha találunk egy nagyon bonyolult feltételes utasítással rendelkező forró módszert, akkor meg kell próbálnunk elválasztani a ha-utasítást, és növelje a részletességet, hogy a JIT optimalizálni tudja a kódot. Ugyanez vonatkozik a kapcsoló és for-hurok állítások.

Arra a következtetésre juthatunk, hogy a kézi metódus beillesztése nem szükséges a kódunk optimalizálása érdekében. A JVM hatékonyabban csinálja, és valószínűleg hosszú és nehezen követhetővé tennénk a kódot.

4.1. Példa

Most nézzük meg, hogyan ellenőrizhetjük ezt a gyakorlatban. Először létrehozunk egy egyszerű osztályt, amely kiszámítja az első összegét N egymást követő pozitív egész számok:

nyilvános osztály ConsecutiveNumbersSum {private long totalSum; private int totalNumbers; public ConsecutiveNumbersSum (int totalNumbers) {this.totalNumbers = totalNumbers; } public long getTotalSum () {totalSum = 0; for (int i = 0; i <összes szám; i ++) {totalSum + = i; } return totalSum; }}

Ezután egy egyszerű módszer felhasználja az osztályt a számítás elvégzéséhez:

privát statikus hosszú calcSum (int n) {return new ConsecutiveNumbersSum (n) .getTotalSum (); }

Végül többször felhívjuk a módszert, és megnézzük, mi történik:

for (int i = 1; i <SZÁMOK_OF_ITERÁCIÓK; i ++) {kiszámítja (I); }

Első távon 1000-szer fogjuk futtatni (kevesebb, mint a fent említett 10 000-es küszöbérték). Ha a kimeneten a calcSum () módszer, nem fogjuk megtalálni. Ez várható, mivel nem hívtuk elégszer.

Ha most megváltoztatjuk az iterációk számát 15 000-re, és újra megkeresjük a kimenetet, akkor látni fogjuk:

664 262% com.baeldung.inlining.InliningExample :: main @ 2 (21 bájt) @ 10 com.baeldung.inlining.InliningExample :: calcSum (12 bájt) inline (hot)

Láthatjuk, hogy ezúttal a módszer teljesíti a beillesztés feltételeit, és a JVM beiktatta.

Figyelemre méltó még egyszer megemlíteni, hogy ha a módszer túl nagy, a JIT nem sorolja be, függetlenül az ismétlések számától. Ezt úgy ellenőrizhetjük, hogy az alkalmazás futtatásakor hozzáadunk egy másik jelölőt:

-XX: FreqInlineSize = 10

Ahogy az előző kimeneten láthatjuk, módszerünk mérete 12 bájt. A -XX:FreqInlineSize A flag a beillesztésre alkalmas módszer méretét 10 bájtra korlátozza. Következésképpen a vonalvezetésre ezúttal nem kerülhet sor. És valóban megerősíthetjük ezt azzal, hogy egy újabb pillantást vetünk a kimenetre:

330 266% com.baeldung.inlining.InliningExample :: main @ 2 (21 bájt) @ 10 com.baeldung.inlining.InliningExample :: calcSum (12 bájt) forró módszer túl nagy

Bár szemléltetés céljából itt megváltoztattuk a jelző értékét, hangsúlyoznunk kell azt az ajánlást, hogy ne változtassuk meg a -XX: FreqInlineSize zászló, hacsak nem feltétlenül szükséges.

5. Következtetés

Ebben a cikkben megnéztük, hogy milyen módszer a beillesztés a JVM-ben, és hogyan csinálja a JIT. Leírtuk, hogyan ellenőrizhetjük, hogy módszereink alkalmasak-e beillesztésre, vagy sem, és javasoltuk, hogyan lehet felhasználni ezeket az információkat azáltal, hogy megpróbáljuk csökkenteni a gyakran hívott hosszú módszerek méretét, amelyek túl nagyok ahhoz, hogy beilleszkedjenek.

Végül bemutattuk, hogyan lehet azonosítani a forró módszert a gyakorlatban.

A cikkben említett összes kódrészlet megtalálható a GitHub-adattárunkban.