Native compilation i Quarkus - hvorfor det er vigtigt

Hej alle! Dette er det andet indlæg i vores Quarkus-serie - i dag taler vi om indbygget kompilering.

Native compilation i Quarkus - hvorfor det er vigtigt

kvarkus er en Java-stak skræddersyet til Kubernetes. Selvom der helt sikkert er meget mere at gøre her, har vi gjort en masse godt arbejde på mange aspekter, herunder optimering af JVM og en række rammer. En af funktionerne ved Quarkus, der har tiltrukket sig øget interesse fra udviklere, er dens omfattende, sømløse tilgang til at omdanne Java-kode til eksekverbare filer til et specifikt operativsystem (såkaldt "native compilation"), der ligner C og C++, hvor en sådan kompilering forekommer normalt i slutningen af ​​en cyklus med opbygning, test og implementering.

Og selvom indbygget kompilering er vigtig, som vi vil vise nedenfor, skal det bemærkes, at Quarkus kører rigtig godt på den mest almindelige Java-maskine, OpenJDK Hotspot, takket være de præstationsforbedringer, vi har implementeret i hele stakken. Derfor bør native compilation betragtes som en ekstra bonus, der kan bruges som ønsket eller nødvendigt. Faktisk er Quarkus stærkt afhængig af OpenJDK, når det kommer til native billeder. Og dev-tilstanden, som er varmt accepteret af udviklere, sikrer næsten øjeblikkelig test af ændringer på grund af de avancerede muligheder for dynamisk kodekørsel implementeret i Hotspot. Derudover bruges OpenJDK-klassebiblioteket og HotSpot-funktionerne ved oprettelse af native GraalVM-billeder.

Så hvorfor har du brug for indbygget kompilering, hvis alt allerede er perfekt optimeret? Vi vil forsøge at besvare dette spørgsmål nedenfor.

Lad os starte med det åbenlyse: Red Hat har stor erfaring med at optimere JVM'er, stakke og rammer under projektudvikling JBoss, herunder:

  • Den første applikationsserver, der arbejder i skyen på platformen Red Hat OpenShift.
  • Den første applikationsserver til at køre på computere Tilslut PC.
  • Den første applikationsserver at køre på raspberry Pi.
  • En række projekter, der kører på enheder Android.

Vi har beskæftiget os med udfordringerne ved at køre Java-applikationer i skyen og på ressourcebegrænsede enheder (læs: IoT) i mange år og har lært at få mest muligt ud af JVM'en med hensyn til ydeevne og hukommelsesoptimering. Som mange andre har vi arbejdet med indbygget kompilering af Java-applikationer i lang tid igennem G.C.J., Avian, Excelsior JET og endog Dalvik og vi er udmærket klar over fordele og ulemper ved denne tilgang (f.eks. dilemmaet med at vælge mellem universaliteten i "byg én gang – kør hvor som helst" og det faktum, at kompilerede applikationer er mindre og kører hurtigere).

Hvorfor er det vigtigt at overveje disse fordele og ulemper? For i nogle situationer bliver deres forhold afgørende:

  • For eksempel i serverløse/hændelsesdrevne miljøer hvor tjenester skal simpelthen starte i (hård eller blød) realtid for at have tid til at reagere på begivenheder. I modsætning til langlivede persistente tjenester øger varigheden af ​​en koldstart her responstiden på en anmodning kritisk. JVM'en tager stadig en betydelig mængde tid at starte op, og selvom dette i nogle tilfælde kan reduceres med rene hardwaremetoder, kan forskellen mellem et sekund og 5 millisekunder være forskellen mellem liv og død. Ja, her kan du lege med at skabe en varm reserve af Java-maskiner (som vi f.eks. gjorde med portering af OpenWhisk til Knative), men dette i sig selv garanterer ikke, at der vil være nok JVM'er til at behandle anmodninger, efterhånden som belastningen skaleres. Og fra et økonomisk synspunkt er det nok ikke den mest korrekte mulighed.
  • Yderligere er der et andet aspekt, der ofte dukker op: multitenancy. På trods af at JVM'er er kommet meget tæt på operativsystemer i deres muligheder, er de stadig ikke i stand til at gøre det, vi er så vant til i Linux - at isolere processer. Derfor kan fejlen i en tråd ødelægge hele Java-maskinen. Mange mennesker forsøger at omgå denne ulempe ved at dedikere en separat JVM til hver brugers applikation for at minimere konsekvenserne af en fejl. Dette er ret logisk, men passer ikke godt med skalering.
  • For cloud-orienterede applikationer er en vigtig indikator desuden tætheden af ​​tjenester på værten. Overgang til metode 12 anvendelsesfaktorer, mikrotjenester og Kubernetes øger antallet af Java-maskiner pr. applikation. Det vil sige, at alt dette på den ene side giver elasticitet og pålidelighed, men samtidig stiger forbruget af basishukommelse servicemæssigt også, og nogle af disse udgifter er ikke altid strengt nødvendige. Statisk kompilerede eksekverbare filer drager fordel her på grund af forskellige optimeringsteknikker, såsom fjernelse af dødkode på lavt niveau, når det endelige billede kun inkluderer de dele af rammerne (inklusive selve JDK), som tjenesten rent faktisk bruger. Derfor hjælper Quarkus native compilation med at placere serviceforekomster tæt på værten uden at gå på kompromis med sikkerheden.

Faktisk er ovenstående argumenter allerede nok til at forstå berettigelsen af ​​indfødt kompilering fra Quarkus-projektets deltageres synspunkt. Der er dog en anden, ikke-teknisk, men også vigtig grund: I de senere år har mange programmører og udviklingsvirksomheder forladt Java til fordel for nye programmeringssprog, idet de mener, at Java sammen med dets JVM'er, stakke og rammer er blevet for hukommelseskrævende, for langsom osv.

Men vanen med at bruge det samme værktøj til at løse ethvert problem er det er ikke altid rigtigt. Nogle gange er det bedre at tage et skridt tilbage og lede efter noget andet. Og hvis Quarkus får folk til at stoppe op og tænke, så er det godt for hele Java-økosystemet. Quarkus repræsenterer et innovativt syn på, hvordan man bygger mere effektive applikationer, hvilket gør Java mere relevant for nye applikationsarkitekturer som serverløs. Derudover vil Quarkus på grund af dets udvidelsesmuligheder forhåbentlig have et helt økosystem af Java-udvidelser, hvilket markant øger antallet af frameworks, der vil understøtte native kompilering i applikationer ud af boksen.

Kilde: www.habr.com

Tilføj en kommentar