Ako zahriať JVM

1. Prehľad

JVM je jedným z najstarších, ale výkonných virtuálnych strojov, aké boli kedy vyrobené.

V tomto článku sa rýchlo pozrieme na to, čo znamená zahriatie JVM a ako na to.

2. Základy architektúry JVM

Kedykoľvek sa spustí nový proces JVM, všetky požadované triedy sa načítajú do pamäte inštanciou ClassLoader. Tento proces prebieha v troch krokoch:

  1. Načítanie triedy Bootstrap: Zavádzač triedy Bootstrap”Načítava kód Java a základné triedy Java, ako napr java.lang.Objekt do pamäti. Tieto naložené triedy sídlia v JRE \ lib \ rt.jar.
  2. Načítava sa trieda rozšírenia: ExtClassLoader je zodpovedný za načítanie všetkých súborov JAR umiestnených na serveri java.ext.dirs cesta. V aplikáciách, ktoré nepoužívajú Maven alebo Gradle a kde vývojár pridáva súbory JAR ručne, sa všetky tieto triedy načítajú počas tejto fázy.
  3. Načítava sa trieda aplikácie: AppClassLoader načíta všetky triedy umiestnené v ceste k triede aplikácie.

Tento inicializačný proces je založený na lenivej schéme načítania.

3. Čo zohrieva JVM

Po dokončení načítania tried sa všetky dôležité triedy (používané v čase spustenia procesu) natlačia do medzipamäte JVM (natívny kód) - vďaka čomu sú rýchlejšie prístupné počas behu programu. Ostatné triedy sú načítané na základe požiadavky.

Prvá požiadavka predložená webovej aplikácii Java je často podstatne pomalšia ako priemerná doba odozvy počas životnosti procesu. Toto zahrievacie obdobie možno zvyčajne pripísať lenivému načítaniu triedy a kompilácii just-in-time.

Nezabúdajte na to, že v prípade aplikácií s nízkou latenciou musíme všetky triedy vopred uložiť do medzipamäte - aby boli okamžite dostupné pri prístupe za behu.

Tento proces ladenia JVM je známy ako zahriatie.

4. Viacúrovňová kompilácia

Vďaka zvukovej architektúre JVM sa často používané metódy načítavajú do natívnej vyrovnávacej pamäte počas životného cyklu aplikácie.

Túto vlastnosť môžeme využiť na vynútenie načítania kritických metód do medzipamäte pri spustení aplikácie. V tomto rozsahu musíme nastaviť argument VM s názvom Viacúrovňová kompilácia:

-XX: CompileThreshold -XX: TieredCompilation

VM zvyčajne používa tlmočník na zhromažďovanie profilovacích informácií o metódach, ktoré sa vkladajú do kompilátora. V stupňovej schéme sa okrem tlmočníka používa klientsky kompilátor na generovanie kompilovaných verzií metód, ktoré o sebe zhromažďujú profilové informácie.

Pretože kompilovaný kód je podstatne rýchlejší ako interpretovaný kód, program sa vykonáva s lepším výkonom počas fázy profilovania.

Aplikácie bežiace na JBoss a JDK verzie 7 s týmto povoleným argumentom VM majú tendenciu po nejakom čase zlyhať kvôli zdokumentovanej chybe. Tento problém bol opravený v JDK verzie 8.

Ďalším bodom, ktorý je tu potrebné poznamenať, je to, že na vynútenie zaťaženia sa musíme uistiť, že je potrebné pristupovať ku všetkým (alebo väčšine) triedam, ktoré sa majú vykonať. Je to podobné ako s určením pokrytia kódu počas testovania jednotky. Čím viac kódu bude pokrytých, tým lepší bude výkon.

Ďalšia časť ukazuje, ako je to možné implementovať.

5. Ručná implementácia

Na zahriatie JVM môžeme použiť alternatívnu techniku. V takom prípade by jednoduché manuálne zahriatie mohlo zahŕňať opakované vytváranie rôznych tried tisíckrát hneď po spustení aplikácie.

Najskôr musíme vytvoriť atrapu triedy normálnou metódou:

public class Dummy {public void m () {}}

Ďalej musíme vytvoriť triedu, ktorá má statickú metódu, ktorá sa vykoná minimálne 100 000-krát, hneď ako sa aplikácia spustí, a pri každom spustení vytvorí novú inštanciu vyššie uvedenej fiktívnej triedy, ktorú sme vytvorili predtým:

verejná trieda ManualClassLoader {chránené statické void zaťaženie () {pre (int i = 0; i <100000; i ++) {Dummy dummy = new Dummy (); atrapa.m (); }}}

Teraz, aby zmerajte výkonnostný zisk, musíme vytvoriť hlavnú triedu. Táto trieda obsahuje jeden statický blok, ktorý obsahuje priame volanie na Načítanie ManualClassLoader () metóda.

Vo vnútri hlavnej funkcie zavoláme na Načítanie ManualClassLoader () ešte raz a zachytiť systémový čas v nanosekundách tesne pred a po našom vyvolaní funkcie. Nakoniec tieto časy odpočítame, aby sme získali skutočný čas vykonania.

Aplikáciu musíme spustiť dvakrát; raz s naložiť() volanie metódy vo vnútri statického bloku a raz bez tohto volania metódy:

public class MainApplication {static {long start = System.nanoTime (); ManualClassLoader.load (); dlhý koniec = System.nanoTime (); System.out.println ("Čas zahrievania:" + (koniec - štart)); } public static void main (String [] args) {long start = System.nanoTime (); ManualClassLoader.load (); dlhý koniec = System.nanoTime (); System.out.println ("Celkový čas:" + (koniec - začiatok)); }}

Výsledky sa reprodukujú v nanosekundách:

S programom Warm UpŽiadne rozcvičenieRozdiel(%)
1220056 8903640 730
1083797 13609530 1256
1026025 9283837 905
1024047 7234871 706
868782 9146180 1053

Podľa očakávania prístup pri zahriatí vykazuje oveľa lepší výkon ako normálny.

Samozrejme, toto je veľmi zjednodušujúce kritérium a poskytuje iba určitý povrchový vhľad do dopadu tejto techniky. Je tiež dôležité pochopiť, že s aplikáciou v reálnom svete sa musíme zahriať typickými kódovými cestami v systéme.

6. Nástroje

Na zahriatie JVM môžeme použiť aj niekoľko nástrojov. Jedným z najznámejších nástrojov je Java Microbenchmark Harness, JMH. Spravidla sa používa na mikro-benchmarking. Po načítaní opakovane narazí na útržok kódu a sleduje iteračný cyklus zahrievania.

Aby sme to mohli použiť, musíme pridať ďalšiu závislosť do pom.xml:

 org.openjdk.jmh jmh-core 1,19 org.openjdk.jmh jmh-generator-annprocess 1,19 

Najnovšiu verziu JMH môžeme skontrolovať v centrálnom úložisku Maven.

Prípadne môžeme na vytvorenie vzorového projektu použiť plugin maven od JMH:

mvn archetype: generate \ -DinteractiveMode = false \ -DarchetypeGroupId = org.openjdk.jmh \ -DarchetypeArtifactId = jmh-java-benchmark-archetype \ -DgroupId = com.baeldung \ -DartifactId = test \ -Dversion = 1,0

Ďalej vytvoríme a hlavný metóda:

public static void main (String [] args) hodí RunnerException, IOException {Main.main (args); }

Teraz musíme vytvoriť metódu a anotovať ju pomocou JMH @Benchmark anotácia:

@Benchmark public void init () {// fragment kódu}

Vo vnútri tohto init metóda, musíme napísať kód, ktorý je potrebné opakovane vykonávať, aby sa zahrial.

7. Benchmark výkonnosti

Za posledných 20 rokov sa väčšina príspevkov do Javy týkala GC (Garbage Collector) a JIT (Just In Time Compiler). Takmer všetky výkonové ukazovatele nájdené online sa vykonávajú na prostredí JVM, ktoré už nejaký čas beží. Avšak

Avšak Univerzita v Beihangu zverejnil referenčnú správu zohľadňujúcu čas zahrievania JVM. Na spracovanie masívnych údajov použili systémy založené na Hadoop a Spark:

Tu HotTub označuje prostredie, v ktorom bol JVM zahriaty.

Ako vidíte, zrýchlenie môže byť značné, najmä pri relatívne malých operáciách čítania - z tohto dôvodu je zaujímavé tieto údaje brať do úvahy.

8. Záver

V tomto rýchlom článku sme si ukázali, ako JVM načítava triedy pri spustení aplikácie a ako môžeme JVM zahriať, aby sme dosiahli zvýšenie výkonu.

Táto kniha obsahuje ďalšie informácie a pokyny týkajúce sa tejto témy, ak chcete pokračovať.

Celý zdrojový kód je ako vždy k dispozícii na GitHub.


$config[zx-auto] not found$config[zx-overlay] not found