Java >> Java tutorial >  >> Java

Apache Camel 3.7 – Flere kamelkerne-optimeringer på vej (Del 5)

Jeg har tidligere blogget om de optimeringer, vi laver i Apache Camel-kernen. De første 3 blogs (del1, del2, del3) var et stykke tid tilbage før 3.4 LTS-udgivelsen.

Nu har vi gjort noget mere arbejde (part4) og denne del 5, der kommer op i den næste 3.7 LTS-udgivelse.

Denne gang har vi primært fokuseret på at reducere fodaftrykket af Camel efter bootstrapping.

adskillelse af designtidsmodel vs runtime-processorer

Vi har fortsat modulariseringen og har adskilt designtiden vs runtime delene i kernen.

Rutemodellen er nu i camel-core-model, og runtime EIP-implementeringerne er i camel-core-processor. Og ind imellem har vi camel-core-reifier, som forvandler modellen til processorer. Denne adskillelse spiller en væsentlig del af den fortsatte indsats for at gøre Camel endnu mindre, såsom Quarkus og GraalVM runtimes. Dette vil i det væsentlige give os mulighed for at forudbygge runtime-processorerne ud fra rutemodellen, og så på runtime ikke engang inkludere model- og reifier-klasserne. Der er stadig noget arbejde at nå til målstregen, men Camel 3.7 er et stort skridt fremad.

Letvægtstilstand

For kørselstider, der ikke er Quarkus- eller GraalVM-baserede, så har vi en ny letvægtsswitch i camel-main / CamelContext, der kan slås til, som udfører nogle interne optimeringer ved at nulstille modellen og reifiers fra runtime-processorerne, hvilket så hjælper JVM skraldeopsamleren, så den kan reducere hukommelsen.

De følgende to skærmbilleder viser kamel-eksempel-main-tiny, der kører med Camel 3.4.4 og 3.7.0 (letvægtstilstand).

De øverste skærmbilleder viser, at der er 731 Camel-objekter, og at de fylder omkring 58 kb hukommelse i bunken. Nu i Camel 3.7 er dette blevet væsentligt forbedret, da der kun er 340 objekter, og de fylder 25 kb. Det betyder, at Camel er skrumpet til halvdelen af ​​størrelsen i hukommelsesfodaftryk. Hukommelsen, der refereres til her, er den hukommelse, som Camel bruger til at bootstrap og starte sig selv.

Forbedret typekonverter

Typekonverteringssystemet er blevet optimeret til at være hurtigere til almindelige konverteringer og samtidig reducere antallet af metodekald under en konvertering. Kernekonverterne samles nu og kildekoden genereres i 1 klasse pr. maven artefakter (2 i alt for kerne). Før dette var der omkring 10 forskellige konverterklasser. Dette hjælper med at reducere fodaftrykket af typekonverteringsregistret betydeligt. Nu er alle kernekonvertere kun refereret af 2 klasser. Før hver konvertermetode blev registreret via et dobbeltnøglet kort, som fører til et kort indeholdende 200 konvertere (optager 20 kb af heap-hukommelse). Og oven i købet påkaldes hver konvertermetode via lambda-kald, som JVM kompilerer til en separat klasse (så der var også indlæst 100 ekstra klasser). Så alt sammen reducerer dette fodaftrykket i høj grad ved at sænke brugen af ​​heap-hukommelse med 20 kb og 100 færre klasser indlæst. Og hvis du bruger nogen af ​​XML-komponenterne, kommer camel-core-jaxb/camel-core-jaxp også med 100 konvertere, hvilket betyder, at hvis de blev indlæst, ville det fordoble hukommelsesfodaftrykket. Og typekonverteren er nu også hurtigere, da opslaget af konverteren er hurtigere og kun bruger Java-primitiver, hvor der som tidligere blev oprettet nye objekter som nøgler til opslag i det interne registerkort. Så der er også mindre skrald til GC.

Følgende skærmbillede viser det samme eksempel som før med Camel 3.7.0 (ingen letvægtstilstand):

Her kan vi se, at der er 346 objekter, og de fylder 28kb hukommelse. Det er kun +6 objekter og +3kb mere hukommelse. Så letvægtstilstanden reducerede i dette eksempel ikke så meget hukommelse. Det skyldes, at der kun er 1 rute og 4 forskellige modeller i brug. Hvis applikationen har flere ruter og flere EIP-modeller og reifiers, vil mere hukommelse blive reduceret.

Prisen er dog, at applikationen ikke dynamisk kan tilføje nye ruter (via modellen). Letvægtstilstanden skal bruges med forsigtighed, og den er kun til "statiske kamelapplikationer".

Optimeret direkte komponent

Den direkte komponent er blevet optimeret til at forbinde sine producenter og forbrugere under opstart. Før den direkte producent ville for hver besked derefter slå den tilknyttede forbruger op, før den sendte beskeden til forbrugeren. Vi har flyttet dette til en tidligere fase. Og så i tilfælde af at en forbruger stoppes / fjernes / eller genskabes osv., så er producenten i stand til at ugyldiggøre sin gamle ledning og gentilknytte den nye forbruger. Dette forbedrede undgår intern opslag og trådsynkronisering.

Optimeret hændelsesunderretning

En anden forbedring af ydeevnen var at opdele hændelsesmeddelelser i livscyklus versus meddelelsesbegivenheder. Da livscyklushændelser såsom start og stop af Camel ikke påvirker, hvad der sker under routing af beskeder. Vi bruger denne viden til at undgå at tjekke for runtime-hændelser i routingmotoren, hvis der ikke er tilføjet nogen tilpasset livscyklus til Camel.

Parsing uden regulære udtryk

Nogle dele i Camel bruger regulære udtryk til at parse, såsom en streng til langtidskonvertering, så du kan konvertere 10m30s (som 10 minutter og 30 sekunder). Dette brugte flere regulære udtryk. Men når de bliver kompileret af JVM, er de objekter i hukommelsen ret store. Der er andre steder internt i Camel, hvor regulære udtryk blev brugt til mere grundlæggende parsing. Så vi omskrev dem, der brugte almindelig grundlæggende Java, og dette reducerede hukommelsen og har bedre ydeevne. Som at bruge regulære udtryk i første omgang var en smule overkill.

BootstrapCloseable

Navngivning i IT er svært, så vi navngav en ny markørgrænseflade BootstrapCloseable efter java.io.Closeable. Vi bruger dette til at markere tjenester og andre enheder i Camel som noget, der kun bruges under bootstrapping af Camel. Så efter at Camel er startet, vil vi så påkalde dem, så de kan frigøre ressourcer og hukommelse.

Mere på vej

Der kommer mere til Camel 3.7. Men på dette tidspunkt ønskede vi at dele den gode nyhed om, at Camel er på diæt og er skrumpet til halvdelen af ​​størrelsen for dens hukommelsesfodaftryk (opstart).

Vi har planer om at se på et kompileret simpelt sprog, som i høj grad ville forbedre ydeevnen for nogle simple udtryk, der er dynamiske og bruger metodekald. Et inspirationsområde er det nye camel-joor-sprog, som bliver kompileret til Java under bootstrap.

Java tag