Jak rozgrzać klasy Java, aby uniknąć wolnego pierwszego połączenia?

13

Realizuję projekt, w którym potrzebuję wszystkich wywołań interfejsu API, aby trwały krócej niż 1s, ale mam problem z pierwszym wywołaniem każdej trasy, który jest wolniejszy niż kolejne.

Obecnie pierwsze połączenie z logowaniem trwa 3,6 sekundy, a kolejne 170 ms i tak samo dla wszystkich pozostałych tras.

Dowiedziałem się, -XX:+TraceClassLoadingże przy pierwszym wywołaniu klasy zostały załadowane do pamięci, co spowodowało problem z wydajnością.

Jednak nie znalazłem łatwego sposobu na załadowanie wszystkich klas podczas uruchamiania i do każdej nowej usługi muszę dodać wywołanie rozgrzewające w ApplicationRunner.

Czy ktoś ma rozwiązanie, aby automatycznie załadować klasy aplikacji SpringBoot lub rozgrzać wszystkie jej trasy?

Ybri
źródło
Czy możesz dodać więcej szczegółów? Czy twoja aplikacja tworzy instancje kontrolerów? A może dzwonisz do innych usług? Jak dzwonisz do innych usług?
Menios
Spring Boot intensywnie korzysta ze skanowania klas, więc nie trzeba „rozgrzewać” niczego, jak na komputerze. To długie początkowe ładowanie może być wynikiem przeszukiwania zasobów - na przykład ładowania szablonu strony.
Alex Chernyshev
Trochę pośredniego podejścia: jeśli masz 100% pokrycia testem jednostkowym dla punktów końcowych, możesz ich użyć. Nadal będziesz musiał kodować według punktu końcowego, ale coś zyskasz
Marged
1
Może nie być idealny w zależności od wykonywanego projektu, ale możesz wywoływać punkty końcowe wewnętrznie, gdy aplikacja zostanie załadowana.
omoshiroiii
@omoshiroiii nie ma w tym nic złego. robimy to. w produkcji. powód ma związek z niektórymi bibliotekami dynamicznymi, które używają, invokedynamici wiemy, że rozdzielczość przy pierwszym wywołaniu jest powolna (mamy dziesiątki tysięcy takich wywołań, które bez tego pierwszego połączenia kumulują się do dziesiątek sekund).
Eugene

Odpowiedzi:

1

Ładowanie klasy Java jest leniwe. Oznacza to, że klasa jest ładowana przez JVM tylko wtedy, gdy jest to konieczne i jeśli jest to konieczne.

Jeśli chcesz zmusić go do niecierpliwego ładowania klas, musisz po prostu do nich odwoływać. Jednym ze sposobów jest iteracja zawartości jar lub plików klas, aby uzyskać nazwy klas, a następnie użyć ich do wywołania Class.forName(className).

Dodatkowo, jeśli czas uruchamiania i wydajność są bardzo ważne w twoim przypadku użycia, możesz chcieć przyjrzeć się rozwiązaniom kompilacji przed czasem, takim jak GraalVM , lub zmniejszyć próg JIT dla kompilacji ( -XX:CompileThreshold).

andresp
źródło
żadne z nich nie rozwiąże problemu OP. ładowanie jest nadal leniwe w GraalVM i naprawdę JITnie ma znaczenia przy pierwszych wywołaniach, naprawdę.
Eugene
też GraalVMjest dobre, ale proszę spojrzeć na liczbę problemów, które ma w github: jak tylko przejdziesz z projektu piaskownicy do czegoś większego (głównie patrzę na twoje odbicie), będziesz odczuwał ból, przynajmniej. Chodzi mi o to: przejście na GraalVM nie jest zwykłym pstryknięciem palców.
Eugene
Myślałem o załadowaniu klas do słoika, ale nie znalazłem sposobu na zrobienie tego, czy masz przykład?
Ybri
@Eugene, jeśli przeczytasz moją odpowiedź, zobaczysz, że nie powiedziałem, że GraalVM lub próg JIT zmieniłby lenistwo ładowania klas. Odpowiedzią na pytanie OP dotyczące lenistwa jest akapit przed nim. Ostatni akapit to tylko dodatkowa wskazówka na wypadek, gdyby OP musiał dalej optymalizować czas uruchamiania / wydajność poza obciążeniem klasy.
i
1
@Ybri istnieją inne pytania z odpowiedziami na które tu np stackoverflow.com/questions/2370867/...
andresp
0

Dla mnie jedyną realną opcją masz to class data sharing, rozłożone JEP 310 , JEP 341 i JEP 350 , ale to wymaga java-13 najprawdopodobniej. Testujemy to wewnętrznie w moim miejscu pracy (głównie dla zabawy, nie będę kłamać), a wyniki do tej pory wyglądają dobrze.

Inną opcją jest wywoływanie punktów końcowych podczas uruchamiania aplikacji - jeśli jest to opcja. Ponownie, jest to dla nas na przykład: nazywamy je z danymi atrapy kilka setek razy, aby rozgrzać kod. Ale jednocześnie mamy usługi, w których byłoby to niemożliwe - dlatego też odkrywanie CDS.

Eugene
źródło
Jak radzisz sobie z uwierzytelnianiem i końcowymi punktami końcowymi, aby uniknąć tworzenia danych w produkcyjnej bazie danych?
Ybri
@Ybri dokładnie dlaczego powiedziałem, dla niektórych niemożliwe .
Eugene