Natywna kompilacja w Quarkusie - dlaczego to ważne

Cześć wszystkim! To drugi post z naszej serii o Quarkusie - dziś porozmawiamy o kompilacji natywnej.

Natywna kompilacja w Quarkusie - dlaczego to ważne

kwarkus to stos Java dostosowany do Kubernetes. Chociaż z pewnością jest tu o wiele więcej do zrobienia, wykonaliśmy dużo dobrej pracy w wielu aspektach, w tym w optymalizacji JVM i szeregu frameworków. Jedną z cech Quarkus, która cieszy się coraz większym zainteresowaniem programistów, jest kompleksowe, bezproblemowe podejście do przekształcania kodu Java w pliki wykonywalne dla konkretnego systemu operacyjnego (tzw. „kompilacja natywna”), podobnie jak w C i C++, gdzie taka kompilacja zwykle ma miejsce na końcu cyklu kompilacji, testowania i wdrażania.

I chociaż natywna kompilacja jest ważna, jak pokażemy poniżej, należy zauważyć, że Quarkus działa naprawdę dobrze na najpopularniejszej maszynie Java, OpenJDK Hotspot, dzięki ulepszeniom wydajności, które wdrożyliśmy w całym stosie. Dlatego natywną kompilację należy traktować jako dodatkowy bonus, który można wykorzystać według uznania lub potrzeby. W rzeczywistości Quarkus w dużym stopniu opiera się na OpenJDK, jeśli chodzi o obrazy natywne. Z kolei ciepło przyjęty przez programistów tryb deweloperski zapewnia niemal natychmiastowe testowanie zmian dzięki zaawansowanym możliwościom dynamicznego wykonywania kodu zaimplementowanym w Hotspocie. Ponadto podczas tworzenia natywnych obrazów GraalVM wykorzystywana jest biblioteka klas OpenJDK i możliwości HotSpot.

Po co więc natywna kompilacja, skoro wszystko jest już doskonale zoptymalizowane? Postaramy się odpowiedzieć na to pytanie poniżej.

Zacznijmy od oczywistości: Red Hat ma rozległe doświadczenie w optymalizacji maszyn JVM, stosów i frameworków podczas tworzenia projektu JBosswłącznie z:

  • Pierwszy serwer aplikacji pracujący w chmurze na platformie Red Hat OpenShift.
  • Pierwszy serwer aplikacji do uruchamiania na komputerach Podłącz komputer.
  • Pierwszy serwer aplikacji, na którym można działać Raspberry Pi.
  • Szereg projektów działających na urządzeniach Android.

Od wielu lat radzimy sobie z wyzwaniami związanymi z uruchamianiem aplikacji Java w chmurze i na urządzeniach o ograniczonych zasobach (czytaj: IoT) i nauczyliśmy się jak najlepiej wykorzystywać JVM pod względem wydajności i optymalizacji pamięci. Podobnie jak wiele innych, od długiego czasu pracujemy nad natywną kompilacją aplikacji Java G.C.J., Ptasia, Excelsior JET i nawet Dalvik i doskonale zdajemy sobie sprawę z zalet i wad tego podejścia (na przykład dylematu wyboru pomiędzy uniwersalnością „zbuduj raz – uruchom gdziekolwiek” a faktem, że skompilowane aplikacje są mniejsze i działają szybciej).

Dlaczego ważne jest rozważenie tych zalet i wad? Ponieważ w niektórych sytuacjach ich stosunek staje się decydujący:

  • Na przykład w środowiskach bezserwerowych/sterowanych zdarzeniami, gdzie usługi muszą po prostu zostać uruchomione w (twardym lub miękkim) czasie rzeczywistym, aby mieć czas na reakcję na zdarzenia. W przeciwieństwie do długotrwałych usług trwałych, w tym przypadku czas zimnego startu krytycznie wydłuża czas odpowiedzi na żądanie. Uruchomienie maszyny JVM nadal zajmuje dużo czasu i choć w niektórych przypadkach można to skrócić za pomocą metod czysto sprzętowych, różnica między jedną sekundą a 5 milisekundami może decydować o życiu lub śmierci. Tak, tutaj możesz pobawić się tworzeniem gorącej rezerwy maszyn Java (co zrobiliśmy np przenoszenie OpenWhisk na Knative), ale to samo w sobie nie gwarantuje, że będzie wystarczająca liczba maszyn JVM do przetwarzania żądań w miarę skalowania obciążenia. Z ekonomicznego punktu widzenia nie jest to prawdopodobnie najwłaściwsza opcja.
  • Ponadto często pojawia się inny aspekt: ​​wielodostępność. Pomimo tego, że JVM swoimi możliwościami bardzo zbliżyły się do systemów operacyjnych, to nadal nie są w stanie robić tego, do czego jesteśmy tak przyzwyczajeni w Linuksie – izolowania procesów. Dlatego awaria jednego wątku może spowodować awarię całej maszyny Java. Wiele osób próbuje obejść tę wadę, dedykując oddzielną maszynę JVM dla każdej aplikacji użytkownika, aby zminimalizować konsekwencje awarii. Jest to całkiem logiczne, ale nie pasuje dobrze do skalowania.
  • Ponadto w przypadku aplikacji zorientowanych na chmurę ważnym wskaźnikiem jest gęstość usług na hoście. Przejście do metodologii 12 czynników aplikacyjnych, mikrousługi i Kubernetes zwiększają liczbę maszyn Java na aplikację. Oznacza to, że z jednej strony wszystko to zapewnia elastyczność i niezawodność, ale jednocześnie wzrasta również zużycie pamięci bazowej pod względem usług, a niektóre z tych wydatków nie zawsze są absolutnie konieczne. Statycznie skompilowane pliki wykonywalne są tutaj korzystne ze względu na różne techniki optymalizacji, takie jak eliminacja martwego kodu na niskim poziomie, gdy ostateczny obraz zawiera tylko te części frameworków (w tym sam JDK), z których faktycznie korzysta usługa. Dlatego natywna kompilacja Quarkus pomaga gęsto umieszczać instancje usług na hoście bez narażania bezpieczeństwa.

Właściwie powyższe argumenty są już wystarczające, aby zrozumieć uzasadnienie kompilacji natywnej z punktu widzenia uczestników projektu Quarkus. Istnieje jednak inny, nietechniczny, ale także ważny powód: w ostatnich latach wielu programistów i firm programistycznych porzuciło Javę na rzecz nowych języków programowania, wierząc, że Java wraz z jej maszynami JVM, stosami i frameworkami stała się zbyt żądny pamięci, zbyt wolny itp.

Jednak nawyk używania tego samego narzędzia do rozwiązania dowolnego problemu jest nie zawsze jest to w porządku. Czasami lepiej cofnąć się o krok i poszukać czegoś innego. A jeśli Quarkus zmusza ludzi do zatrzymania się i zastanowienia, jest to dobre dla całego ekosystemu Java. Quarkus reprezentuje innowacyjne spojrzenie na tworzenie bardziej wydajnych aplikacji, dzięki czemu Java jest bardziej dostosowana do nowych architektur aplikacji, takich jak aplikacje bezserwerowe. Ponadto, ze względu na swoją rozszerzalność, mamy nadzieję, że Quarkus będzie miał cały ekosystem rozszerzeń Java, znacznie zwiększając liczbę frameworków, które będą wspierać natywną kompilację w aplikacjach od razu po wyjęciu z pudełka.

Źródło: www.habr.com

Dodaj komentarz