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.