Cara Memanaskan JVM

1. Gambaran keseluruhan

JVM adalah salah satu mesin maya tertua yang kuat dan pernah dibina

Dalam artikel ini, kita melihat dengan cepat apa artinya memanaskan JVM dan cara melakukannya.

2. Asas Senibina JVM

Setiap kali proses JVM baru dimulakan, semua kelas yang diperlukan dimuat ke dalam memori dengan menggunakan ClassLoader. Proses ini berlaku dalam tiga langkah:

  1. Pemuatan Kelas Bootstrap: " Bootstrap Class Loader " memuat kod Java dan kelas Java penting seperti java.lang.Object ke dalam memori. Kelas yang dimuat ini berada di JRE \ lib \ rt.jar .
  2. Pemuatan Kelas Sambungan : ExtClassLoader bertanggungjawab memuat semua fail JAR yang terletak di jalan java.ext.dirs . Dalam aplikasi berasaskan bukan Maven atau bukan Gradle, di mana pembangun menambah JAR secara manual, semua kelas dimuat semasa fasa ini.
  3. Pemuatan Kelas Aplikasi : AppClassLoader memuatkan semua kelas yang berada di laluan kelas aplikasi.

Proses inisialisasi ini berdasarkan skema pemuatan yang malas.

3. Apa yang Memanaskan JVM

Setelah pemuatan kelas selesai, semua kelas penting (digunakan pada masa proses dimulakan) dimasukkan ke dalam cache JVM (kod asli) - yang menjadikannya lebih mudah diakses semasa waktu proses. Kelas lain dimuat berdasarkan permintaan.

Permintaan pertama yang dibuat ke aplikasi web Java biasanya jauh lebih lambat daripada waktu respons rata-rata selama proses berlangsung. Tempoh pemanasan ini biasanya disebabkan oleh pemuatan kelas yang malas dan penyusunan tepat pada waktunya.

Perlu diingat, untuk aplikasi latensi rendah, kita perlu menyimpan semua kelas terlebih dahulu - supaya mereka tersedia serta-merta ketika diakses pada waktu runtime.

Proses penalaan JVM ini dikenali sebagai pemanasan.

4. Penyusunan Bertingkat

Terima kasih kepada seni bina JVM yang baik, kaedah yang sering digunakan dimasukkan ke dalam cache asli semasa kitaran hidup aplikasi.

Kami boleh menggunakan harta ini untuk memaksa memuatkan kaedah kritikal ke dalam cache semasa aplikasi dimulakan. Sejauh itu, kita perlu menetapkan argumen VM bernama Tiered Compilation :

-XX:CompileThreshold -XX:TieredCompilation

Biasanya, VM menggunakan jurubahasa untuk mengumpulkan maklumat profil mengenai kaedah yang dimasukkan ke dalam penyusun. Dalam skema berjenjang, sebagai tambahan kepada jurubahasa, penyusun pelanggan digunakan untuk menghasilkan versi kaedah yang dikumpulkan yang mengumpulkan maklumat profil tentang diri mereka sendiri.

Oleh kerana kod yang disusun jauh lebih cepat daripada kod yang ditafsirkan, program ini dijalankan dengan prestasi yang lebih baik semasa fasa profil.

Aplikasi yang dijalankan pada JBoss dan JDK versi 7 dengan argumen VM ini diaktifkan cenderung mogok setelah beberapa waktu kerana bug yang didokumentasikan. Masalahnya telah diperbaiki dalam JDK versi 8.

Perkara lain yang perlu diperhatikan di sini adalah bahawa untuk memaksakan pemuatan, kita harus memastikan bahawa semua (atau kebanyakan) kelas yang akan dijalankan perlu diakses. Ia serupa dengan menentukan liputan kod semasa ujian unit. Semakin banyak kod yang dilindungi, prestasi akan semakin baik.

Bahagian seterusnya menunjukkan bagaimana ini dapat dilaksanakan.

5. Pelaksanaan Manual

Kami mungkin menerapkan teknik alternatif untuk memanaskan JVM. Dalam kes ini, pemanasan manual yang sederhana dapat merangkumi pengulangan penciptaan kelas yang berlainan beribu-ribu kali sebaik sahaja aplikasi dimulakan.

Pertama, kita perlu membuat kelas dummy dengan kaedah biasa:

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

Seterusnya, kita perlu membuat kelas yang mempunyai kaedah statik yang akan dilaksanakan sekurang-kurangnya 100000 kali sebaik sahaja aplikasi dimulakan dan dengan setiap pelaksanaan, ia akan membuat contoh baru dari kelas dummy yang telah kita buat sebelumnya:

public class ManualClassLoader { protected static void load() { for (int i = 0; i < 100000; i++) { Dummy dummy = new Dummy(); dummy.m(); } } }

Sekarang, untuk mengukur peningkatan prestasi , kita perlu membuat kelas utama. Kelas ini mengandungi satu blok statik yang mengandungi panggilan terus ke kaedah beban ManualClassLoader () .

Di dalam fungsi utama, kami membuat panggilan ke kaedah LoadClassLoader Manual () sekali lagi dan menangkap masa sistem dalam nanodetik sebelum dan selepas panggilan fungsi kami. Akhirnya, kita tolak kali ini untuk mendapatkan masa pelaksanaan yang sebenarnya.

Kita mesti menjalankan aplikasi dua kali; sekali dengan kaedah panggilan beban () di dalam blok statik dan sekali tanpa kaedah ini panggil:

public class MainApplication { static { long start = System.nanoTime(); ManualClassLoader.load(); long end = System.nanoTime(); System.out.println("Warm Up time : " + (end - start)); } public static void main(String[] args) { long start = System.nanoTime(); ManualClassLoader.load(); long end = System.nanoTime(); System.out.println("Total time taken : " + (end - start)); } }

Di bawah hasilnya dihasilkan dalam nanodetik:

Dengan Pemanasan Tidak Memanaskan Beza(%)
1220056 8903640 730
1083797 13609530 1256
1026025 9283837 905
1024047 7234871 706
868782 9146180 1053

Seperti yang dijangkakan, dengan pendekatan pemanasan menunjukkan prestasi yang jauh lebih baik daripada yang biasa.

Sudah tentu, ini adalah penanda aras yang sangat sederhana dan hanya memberikan beberapa pandangan tahap permukaan mengenai kesan teknik ini. Juga, penting untuk memahami bahawa, dengan aplikasi dunia nyata, kita perlu melakukan pemanasan dengan jalur kod khas dalam sistem.

6. Alat

We can also use several tools to warm up the JVM. One of the most well-known tools is the Java Microbenchmark Harness, JMH. It's generally used for micro-benchmarking. Once it is loaded, it repeatedly hits a code snippet and monitors the warm-up iteration cycle.

To use it we need to add another dependency to the pom.xml:

 org.openjdk.jmh jmh-core 1.19   org.openjdk.jmh jmh-generator-annprocess 1.19 

We can check the latest version of JMH in Central Maven Repository.

Alternatively, we can use JMH's maven plugin to generate a sample project:

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

Next, let's create a main method:

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

Now, we need to create a method and annotate it with JMH's @Benchmark annotation:

@Benchmark public void init() { //code snippet }

Inside this init method, we need to write code that needs to be executed repeatedly in order to warm up.

7. Performance Benchmark

In the last 20 years, most contributions to Java were related to the GC (Garbage Collector) and JIT (Just In Time Compiler). Almost all of the performance benchmarks found online are done on a JVM already running for some time. However,

However, Beihang University has published a benchmark report taking into account JVM warm-up time. They used Hadoop and Spark based systems to process massive data:

Here HotTub designates the environment in which the JVM was warmed up.

As you can see, the speed-up can be significant, especially for relatively small read operations – which is why this data is interesting to consider.

8. Conclusion

In this quick article, we showed how the JVM loads classes when an application starts and how we can warm up the JVM in order gain a performance boost.

Buku ini memuatkan lebih banyak maklumat dan garis panduan mengenai topik ini jika anda mahu meneruskannya.

Dan, seperti biasa, kod sumber penuh tersedia di GitHub.