Java >> Java tutorial >  >> Java

Reduktion af hyppigheden af ​​større GC-pauser


Dette indlæg vil diskutere en teknik til at reducere den byrde, der pålægges pauser i forbindelse med affaldsindsamling på latensen af ​​din Ansøgning. Som jeg har skrevet for et par år siden, er det ikke muligt at deaktivere affaldsindsamling i JVM. Men der er et smart trick, der kan bruges til at reducere længden og hyppigheden af ​​de lange pauser betydeligt.

Som du ved, er der to forskellige GC-begivenheder, der finder sted inden for JVM, kaldet mindre og større samlinger. Der er meget materiale tilgængeligt om, hvad der foregår under de indsamlinger, så jeg vil ikke fokusere på at beskrive mekanikken i detaljer. Jeg vil lige minde om, at i Hotspot JVM – under mindre indsamling, samles eden og overlevende pladser, i større indsamling bliver den faste plads også renset og (eventuelt) komprimeret.

Hvis du slår GC-logningen til (-XX:+PrintGCDetails for eksempel) så bemærker du med det samme, at de store kollektioner er dem, du skal fokusere på. Længden af ​​en større affaldsindsamling, der finder sted, er typisk flere gange større end den, der renser ungt rum. Under en større GC er der to aspekter, der kræver mere tid at gennemføre. Først og fremmest bliver de efterladte fra det unge rum kopieret til gamle. Udover at rense de ubrugte referencer fra den gamle generation, komprimerer de fleste af GC-algoritmerne også det gamle rum, hvilket igen kræver, at dyrebare CPU-cyklusser skal brændes.

At have mange genstande i det gamle rum øger også sandsynligheden for at have flere referencer fra gammelt rum til ungt rum. Dette resulterer i større korttabeller, holder styr på referencerne og øger længden af ​​de mindre GC-pauser, når disse tabeller kontrolleres for at afgøre, om objekter i young space er berettiget til GC.

Så hvis vi ikke kan slå affaldsindsamlingen fra, kan vi så sikre os, at disse lange store GC'er kører sjældnere, og at referenceantallet fra Fast plads til Young forbliver lavt?

Svaret er ja. Der er endda nogle skøre konfigurationer, som har formået at slippe af med den store GC helt. At slippe af med store GC-begivenheder  er virkelig en kompleks øvelse, men at reducere hyppigheden af ​​disse lange pauser er noget, enhver implementering kan opnå.

Den strategi, vi kigger på, er at begrænse antallet af objekter, der bliver fastansat. I en typisk webapplikation for eksempel, er de fleste af de oprettede objekter kun nyttige under HttpRequest . Der er og vil altid være delt tilstand med længere levetid, men nøglen er det faktum, at der er et meget højt forhold mellem kortlivede objekter versus langlivede delte tilstande.

Den vanskelige del for enhver implementering derude nu er at forstå, hvor meget albuerum man skal give til de kortlivede objekter, så

  • Du kan garantere, at de kortlivede objekter ikke bliver forfremmet til fast ejendom
  • Du overprovisionerer ikke, hvilket øger omkostningerne ved din infrastruktur

På konceptuelt niveau er det nemt at opnå dette. Du skal blot måle mængden af ​​hukommelse, der er allokeret til kortlivede objekter under anmodningerne og gange det med spidsbelastningstiden. Det, du ender med, er mængden af ​​hukommelse, du ønsker at passe enten ind i eden eller i et enkelt overlevende rum. Dette vil give GC'en mulighed for at køre virkelig effektivt uden utilsigtede forfremmelser til fastholdelse. Zoom ind fra det konceptuelle niveau viser flere komplekse tekniske problemstillinger, som jeg vil åbne op for i de kommende indlæg.

Så hvad skal man konkludere herfra? Først og fremmest – at bestemme den perfekte GC-konfiguration til din applikation er en kompleks øvelse. Dette er både dårlige og gode nyheder. Dårligt i forhold til det – det kræver mange eksperimenter fra din side. Godt i forhold til det – vi kan godt lide svære problemer, og vi laver i øjeblikket eksperimenter for at undersøge domænet nærmere. En dag, ikke så langt ude i fremtiden, er Plumbr i stand til at gøre det for dig, hvilket sparer dig for et kedeligt VVS-arbejde og giver dig mulighed for at fokusere på det aktuelle problem.

Java tag