Innfødt samling i Quarkus - hvorfor det er viktig

Hei alle sammen! Dette er det andre innlegget i serien vår om Quarkus - i dag skal vi snakke om innfødt kompilering.

Innfødt samling i Quarkus - hvorfor det er viktig

quarkus er en Java-stakk skreddersydd for Kubernetes. Selv om det absolutt er mye mer å gjøre her, har vi gjort mye godt arbeid på mange aspekter, inkludert optimalisering av JVM og en rekke rammeverk. En av funksjonene til Quarkus som har tiltrukket seg økt interesse fra utviklere, er dens omfattende, sømløse tilnærming til å gjøre om Java-kode til kjørbare filer for et spesifikt operativsystem (såkalt "native compilation"), lik C og C++, der slik kompilering skjer vanligvis på slutten av en syklus med bygg, test og distribusjon.

Og selv om innfødt kompilering er viktig, som vi skal vise nedenfor, bør det bemerkes at Quarkus kjører veldig bra på den vanligste Java-maskinen, OpenJDK Hotspot, takket være ytelsesforbedringene vi har implementert gjennom stabelen. Derfor bør innfødt kompilering betraktes som en tilleggsbonus som kan brukes etter ønske eller nødvendig. Faktisk stoler Quarkus sterkt på OpenJDK når det kommer til native bilder. Og utviklermodusen, som er hjertelig akseptert av utviklere, sikrer nesten umiddelbar testing av endringer på grunn av de avanserte mulighetene for dynamisk kodekjøring implementert i Hotspot. I tillegg, når du lager native GraalVM-bilder, brukes OpenJDK-klassebiblioteket og HotSpot-funksjonene.

Så hvorfor trenger du innfødt kompilering hvis alt allerede er perfekt optimalisert? Vi vil prøve å svare på dette spørsmålet nedenfor.

La oss starte med det åpenbare: Red Hat har lang erfaring med å optimalisere JVM-er, stabler og rammeverk under prosjektutvikling JBoss, gjelder også:

  • Den første applikasjonsserveren som jobber i skyen på plattformen Red Hat OpenShift.
  • Den første applikasjonsserveren for kjøring på datamaskiner Plugg PC.
  • Den første applikasjonsserveren å kjøre på Raspberry Pi.
  • En rekke prosjekter som kjører på enheter Android.

Vi har jobbet med utfordringene med å kjøre Java-applikasjoner i skyen og på ressursbegrensede enheter (les: IoT) i mange år og har lært å få mest mulig ut av JVM når det gjelder ytelse og minneoptimalisering. Som mange andre har vi jobbet med native kompilering av Java-applikasjoner i lang tid G.C.J., Avian, Excelsior JET og selv Dalvik og vi er godt klar over fordelene og ulempene med denne tilnærmingen (for eksempel dilemmaet med å velge mellom universaliteten "bygg en gang – kjør hvor som helst" og det faktum at kompilerte applikasjoner er mindre og kjører raskere).

Hvorfor er det viktig å vurdere disse fordelene og ulempene? Fordi i noen situasjoner blir forholdet deres avgjørende:

  • For eksempel i serverløse/hendelsesdrevne miljøer hvor tjenestene må rett og slett starte i (hard eller myk) sanntid for å ha tid til å svare på hendelser. I motsetning til langvarige vedvarende tjenester, øker varigheten av en kaldstart responstiden på en forespørsel kritisk. JVM bruker fortsatt betydelig tid på å starte opp, og selv om dette i noen tilfeller kan reduseres med rene maskinvaremetoder, kan forskjellen mellom ett sekund og 5 millisekunder være forskjellen mellom liv og død. Ja, her kan du leke med å lage en varm reserve av Java-maskiner (som vi for eksempel gjorde med porterer OpenWhisk til Knative), men dette i seg selv garanterer ikke at det vil være nok JVM-er til å behandle forespørsler etter hvert som lasten skaleres. Og fra et økonomisk synspunkt er nok ikke dette det mest riktige alternativet.
  • Deretter er det et annet aspekt som ofte dukker opp: multitenancy. Til tross for at JVM-er har kommet veldig nær operativsystemene i sine evner, er de fortsatt ikke i stand til å gjøre det vi er så vant til i Linux – å isolere prosesser. Derfor kan svikt i én tråd få ned hele Java-maskinen. Mange prøver å omgå denne ulempen ved å dedikere en separat JVM for hver brukers applikasjoner for å minimere konsekvensene av en feil. Dette er ganske logisk, men passer dårlig med skalering.
  • I tillegg, for skyorienterte applikasjoner, er en viktig indikator tettheten av tjenester på verten. Overgang til metodikk 12 bruksfaktorer, mikrotjenester og Kubernetes øker antallet Java-maskiner per applikasjon. Det vil si at alt dette på den ene siden gir elastisitet og pålitelighet, men samtidig øker også forbruket av basisminne servicemessig, og noen av disse utgiftene er ikke alltid strengt nødvendige. Statisk kompilerte kjørbare filer drar nytte av her på grunn av ulike optimaliseringsteknikker, for eksempel eliminering av dødkode på lavt nivå, når det endelige bildet inkluderer bare de delene av rammeverket (inkludert selve JDK) som tjenesten faktisk bruker. Derfor hjelper Quarkus native-kompilering med å plassere tjenesteforekomster tett på verten uten at det går på bekostning av sikkerheten.

Faktisk er argumentene ovenfor allerede nok til å forstå begrunnelsen for innfødt kompilering fra Quarkus-prosjektdeltakernes synspunkt. Det er imidlertid en annen, ikke-teknisk, men også viktig grunn: de siste årene har mange programmerere og utviklingsselskaper forlatt Java til fordel for nye programmeringsspråk, og tror at Java, sammen med JVM-er, stabler og rammeverk, har blitt for minnesulten, for sakte osv.

Vanen med å bruke det samme verktøyet for å løse ethvert problem er imidlertid det er ikke alltid riktig. Noen ganger er det bedre å ta et skritt tilbake og se etter noe annet. Og hvis Quarkus får folk til å stoppe opp og tenke, så er det bra for hele Java-økosystemet. Quarkus representerer et innovativt syn på hvordan man bygger mer effektive applikasjoner, noe som gjør Java mer relevant for nye applikasjonsarkitekturer som serverløs. I tillegg, på grunn av utvidbarheten, vil Quarkus forhåpentligvis ha et helt økosystem av Java-utvidelser, noe som øker antallet rammeverk som vil støtte innfødt kompilering i applikasjoner betraktelig.

Kilde: www.habr.com

Legg til en kommentar