Bagaimana cara menghangatkan kelas java untuk menghindari panggilan lambat pertama?

13

Saya sedang melakukan proyek di mana saya membutuhkan semua panggilan API untuk mengambil kurang dari 1 tetapi saya menghadapi masalah dengan panggilan pertama untuk setiap rute yang lebih lambat dari yang berikut.

Saat ini panggilan pertama ke / masuk membutuhkan 3,6s dan yang berikutnya mengambil 170ms dan sama untuk semua rute lainnya.

Saya menemukan menggunakan -XX:+TraceClassLoadingitu pada panggilan pertama, kelas dimuat dalam memori dan yang menyebabkan masalah kinerja.

Namun saya tidak menemukan cara mudah untuk memuat semua kelas saat memulai dan untuk setiap layanan baru, saya perlu menambahkan panggilan pemanasan dalam ApplicationRunner.

Adakah yang punya solusi untuk memuat kelas aplikasi SpringBoot secara otomatis atau menghangatkan semua rutenya?

Ybri
sumber
Bisakah Anda menambahkan lebih detail? Apakah aplikasi Anda instantiating pengontrol? Atau apakah Anda menelepon layanan lain? Bagaimana Anda melakukan panggilan ke layanan lain?
Menios
Spring Boot menggunakan pemindaian kelas secara intensif, jadi Anda tidak perlu 'melakukan pemanasan' seperti pada aplikasi desktop. Pemuatan awal yang panjang ini bisa merupakan hasil pencarian sumber daya - misalnya pemuatan templat halaman.
Alex Chernyshev
Sedikit pendekatan tidak langsung: jika Anda memiliki cakupan tes unit 100% untuk titik akhir Anda dapat menggunakannya. Anda masih harus kode per titik akhir tetapi Anda mendapatkan sesuatu
Marged
1
Mungkin tidak ideal tergantung pada proyek yang Anda lakukan, tetapi Anda bisa memanggil titik akhir Anda secara internal ketika aplikasi Anda dimuat.
omoshiroiii
@omoshiroiii tidak ada yang salah dengan itu. kita lakukan itu. dalam produksi. alasannya ada hubungannya dengan beberapa perpustakaan dinamis yang digunakan invokedynamicdan kami tahu resolusi lambat pada panggilan pertama untuk mereka (kami memiliki puluhan ribu panggilan seperti itu, yang tanpa panggilan pertama ini terakumulasi hingga puluhan detik).
Eugene

Jawaban:

1

Pemuatan kelas Java malas. Ini berarti kelas hanya dimuat oleh JVM ketika perlu dan jika perlu.

Jika Anda ingin memaksanya memuat kelas dengan bersemangat, Anda hanya perlu merujuknya. Salah satu cara untuk melakukannya adalah dengan menelusuri isi tabung atau file kelas untuk mendapatkan nama kelas dan kemudian menggunakannya untuk menelepon Class.forName(className).

Selain itu, jika waktu dan kinerja startup sangat penting untuk kasus penggunaan Anda, Anda mungkin ingin melihat ke depan dari solusi kompilasi seperti GraalVM , atau mengurangi ambang JIT untuk kompilasi ( -XX:CompileThreshold).

andresp
sumber
tak satu pun dari mereka yang akan memecahkan masalah OP. memuat masih malas di GraalVM dan JITtidak ada artinya pada doa pertama , sungguh.
Eugene
juga, GraalVMbagus, tapi tolong lihat sejumlah masalah yang ada di github: segera setelah Anda beralih dari proyek kotak pasir ke sesuatu yang lebih besar (saya melihat refleksi Anda, terutama), Anda akan merasa sakit, paling sedikit. maksud saya adalah: bertukar ke GraalVM bukanlah menjentikkan jari.
Eugene
Saya berpikir tentang memuat kelas dalam toples tetapi saya tidak menemukan cara untuk melakukannya, apakah Anda punya contoh?
Ybri
@Eugene jika Anda membaca jawaban saya, Anda akan melihat bahwa saya belum mengatakan GraalVM atau ambang JIT akan mengubah kemalasan pemuatan kelas. Jawaban untuk pertanyaan OP tentang kemalasan adalah paragraf sebelum yang itu. Paragraf terakhir hanyalah tip tambahan jika OP perlu lebih mengoptimalkan waktu startup / kinerja di luar pemuatan kelas.
andresp
1
@Ybri ada pertanyaan lain dengan jawaban di sini, misalnya stackoverflow.com/questions/2370867/…
andresp
0

Bagi saya, satu-satunya pilihan yang Anda miliki adalah class data sharing, tersebar di JEP 310 , JEP 341 dan JEP 350 , tetapi ini mungkin membutuhkan java-13. Kami menguji ini secara internal di tempat kerja saya (kebanyakan untuk bersenang-senang, tidak akan berbohong) dan hasilnya terlihat bagus, sejauh ini.

Opsi lainnya adalah memanggil titik akhir Anda ketika aplikasi dimulai - jika itu merupakan opsi. Sekali lagi, itu adalah untuk kita misalnya: kita sebut mereka dengan data dummy beberapa ratusan kali untuk pemanasan kode. Tetapi, pada saat yang sama, kami memiliki layanan di mana ini tidak mungkin - itu sebabnya penjelajahan CDSjuga.

Eugene
sumber
Bagaimana Anda menangani otentikasi dan titik akhir pos untuk menghindari pembuatan data dalam basis data produksi Anda?
Ybri
@Ybri persis mengapa saya katakan, tidak mungkin untuk beberapa
Eugene