Principiile de bază ale configurării colecției de gunoi de la zero

În acest articol, nu aș vrea să mă concentrez asupra principiului colectorului de gunoi - acesta este clar și clar descris aici: habrahabr.ru/post/112676/. Aș dori să trec la principiile practice și caracteristicile cantitative ale înființării Colecției de gunoi în JVM - și să încercați să înțelegeți cum poate fi eficientă.







Caracteristicile cantitative ale evaluării eficacității GC


Luați în considerare următorii indicatori:

  • Lățimea de bandă O măsură care determină capacitatea aplicației de a rula la încărcarea maximă, indiferent de pauzele în timpul construcției și cantitatea de memorie necesară
  • Timp de răspuns Măsura GC, care determină capacitatea unei aplicații de a face față numărului de opriri și fluctuații din GC
  • Dimensiunea memoriei utilizate Cantitatea de memorie necesară pentru funcționarea eficientă a GC

De regulă, caracteristicile enumerate sunt compromise, iar îmbunătățirea uneia dintre ele conduce la costuri pentru restul. Pentru toate aplicațiile, toate cele trei caracteristici sunt importante, dar adesea unul sau două sunt mai importante pentru aplicație - acesta va fi punctul de plecare al configurației.

Principiile de bază ale configurației GC

Luați în considerare trei reguli de bază fundamentale pentru înțelegerea setării GC:
  • Este necesar să se depună eforturi pentru a se asigura că numărul maxim de obiecte este șters atunci când se execută micul GC (colecția minoră de graifă). Acest principiu vă permite să reduceți numărul și frecvența colecției complete de gunoi - a cărui activitate este principala cauză a întârzierilor mari în aplicație
  • Cu cât memoria alocată aplicației este mai mare, cu atât mai bine funcționează colecția de gunoi și caracteristicile cantitative mai bune sunt obținute prin lățimea de bandă și timpul de răspuns
  • Configurați eficient numai 2 din cele 3 caracteristici cantitative - debitul, timpul de răspuns, dimensiunea memoriei alocate - sub valoarea efectivă a mărimii memoriei necesare se înțelege minimizarea acesteia

Vom conduce experimentul pe:

Pentru care modul implicit este serverul și UseParallelGC (lucrarea multithreaded a fazei de colectare a gunoiului mic)

Pentru a estima cantitatea totală de pauză a colectorului de gunoi, puteți rula în modul:

Și rezumați întârzierea pe log gc.log:

În cazul în care real = 0,01 sec este timpul real petrecut pe ansamblu.

Și puteți utiliza VisualVm de utilitate, un plug-in instalat VisualGC, care în mod clar se poate observa alocarea memoriei în diferite zone ale GC (Eden, Survivor1, Survivor2, vechi) și a vedea statisticile privind începutul și durata unei colectare a gunoiului.

Determinarea dimensiunii memoriei necesare


Pentru a începe, avem nevoie pentru a rula aplicația cu cea mai mare cantitate posibilă de memorie decât este, de fapt nevoie de aplicație. Dacă n-am ști inițial cât de mulți vor lua cererea noastră în memorie - puteți rula aplicația fără a specifica -Xmx și -Xms și HotSpot VM va selecta dimensiunea memoriei. Dacă la începutul cererii vom primi OutOfMemory (Java spațiu grămadă sau spațiu PermGen), atunci putem crește iterativ dimensiunea memoriei disponibile (-Xmx sau -XX: PermSize) până când eroarea dispare.
Următorul pas este de a calcula mărimea datelor vii de lungă durată - aceasta este dimensiunea zonelor vechi și permanente de heap după faza completă de colectare a gunoiului. Această dimensiune este cantitatea aproximativă de memorie necesară pentru ca aplicația să funcționeze, puteți să vă uitați la dimensiunea suprafețelor după asamblarea completă pentru ao obține. De obicei, dimensiunea memoriei necesare pentru aplicația -Xms și -Xmx este de 3-4 ori mai mare decât cantitatea de date live. Deci, pentru jurnalul specificat mai sus - valoarea zonei vechi după faza completă de colectare a gunoiului este 349363K. Apoi valoarea sugerată este -Xmx și -Xms

1400 MB. -XX: PermSize și -XX: MaxPermSize este de 1,5 ori mai mare decât PermGenSize după faza completă de colectare a gunoiului - 13324K

20 MB. Dimensiunea generației tinere se presupune a fi de 1-1,5 din volumul datelor live

525 MB. Apoi vom obține linia de start jvm cu următorii parametri:

În VisualVm primim următoarea imagine:

Principiile de bază ale configurării colecției de gunoi de la zero

În doar 30 de secunde de experiment, au fost produse 54 de ansambluri - 31 mici și 23 complete - cu un timp total de oprire de 3.227c. Această întârziere nu poate satisface cerințele necesare - să vedem dacă putem îmbunătăți situația fără a modifica codul aplicației.

Configurarea timpului de răspuns acceptabil








Următorii parametri trebuie măsurați și contabilizați la setarea timpului de răspuns:
  • Măsurarea duratei unei colecții mici de gunoi
  • Măsurarea frecvenței unei colecții mici de gunoi
  • Măsurarea duratei celui mai rău caz de colectare completă a gunoiului
  • Măsurarea frecvenței celui mai rău caz de colectare completă a gunoiului
Ajustarea dimensiunii generației tinere și bătrâne


Timpul necesar pentru punerea în aplicare a fazei unei colecții mici de gunoi depinde în mod direct de numărul de obiecte din generația tânără, cu cât dimensiunea este mai mică - cu atât durata este mai scurtă, dar frecvența crește, deoarece zona începe să se umple mai des. Să încercăm să reducem timpul fiecărui ansamblu mic, reducând mărimea tinerei generații, păstrând în același timp dimensiunea vechii generații. Aproximativ unul poate estima că în fiecare secundă trebuie să clarificăm în generația tânără 50 de fluxuri * 8obiecte * 1Mb

400 Mbps. Rulați cu parametrii:

În VisualVm primim următoarea imagine:

Principiile de bază ale configurării colecției de gunoi de la zero

Timpul total de gunoi nu am fost în măsură să afecteze o mică acumulare - 1,533s - creșterea frecvenței de ansambluri mici, dar timpul total deteriorat - 3661 datorită faptului că a crescut rata de generare vechi și frecvența crescută de a apela o colecție completă de gunoi umple. Pentru a depăși acest lucru - să încerce să mărească dimensiunea vechii generații - termen JVM cu următorii parametri:

Principiile de bază ale configurării colecției de gunoi de la zero

Pauza totală sa îmbunătățit acum la 2.637 s, iar valoarea totală a memoriei necesare pentru aplicație a fost redusă - astfel încât este posibil să se găsească echilibrul potrivit între generația veche și cea tânără pentru a distribui durata de viață a obiectelor într-o aplicație specifică.

Când timpul nu este încă mulțumit cu noi - puteți merge la colectorul de gunoi concurente, inclusiv opțiunea -XX: + UseConcMarkSweepGC - un algoritm care va încerca să efectueze lucrări de fond privind marcarea obiectelor de ștergere într-un flux separat, fluxurile de aplicații paralele.

Configurarea colectorului de gunoi concomitent


ConcMarkSweep GC necesită o reglare mai atentă - unul dintre scopurile principale este reducerea numărului de pauze de oprire în lume în absența spațiului suficient în vechea generație pentru localizarea obiectelor. această fază durează în medie mai mult timp decât faza de colectare completă a gunoiului pentru transferul de gaze cu efect de seră. Ca urmare, durata celui mai grav caz de colectare a gunoiului poate crește, este necesar să se evite deversările frecvente de generații vechi. De regulă, atunci când treceți la ConcMarkSweep, GC recomandă creșterea mărimii vechii generații cu 20-30% - rulați jvm cu parametrii:

Principiile de bază ale configurării colecției de gunoi de la zero

Pauza generală a fost redusă la 1.923 s.

Ajustarea mărimii supraviețuitorului


Sub grafic, puteți vedea distribuția memoriei aplicației prin numărul de tranziții dintre etapele Eden, Survivor1 și Survivor2 înainte de a ajunge la generația veche. Faptul este că o modalitate de a reduce numărul de deversări de generații vechi în ConcMarkSweep GC este de a preveni migrarea directă a obiectelor de la generația tânără direct la vechi - ocolind supraviețuitorul regiunii.

Pentru a urmări distribuția obiectelor în etape, puteți rula jvm cu opțiunea -XX: + PrintTenuringDistribution.
În gc.log putem observa:

Dimensiunea totală a obiectelor supraviețuitoare este de 40900584, în mod implicit CMS folosește o barieră de 50% pentru zona de ocupare a supraviețuitorului. Astfel obținem dimensiunea domeniului

80 MB. Când rulează jvm, este specificat de parametrul -XX: SurvivorRatio, care este determinat de formula:

Dorind să lași dimensiunea eden spațiu la fel - obține:


Principiile de bază ale configurării colecției de gunoi de la zero

Distribuția este mai bine, dar timpul total nu de mult sa schimbat din cauza specificul aplicației, faptul este că, după frecvente colecții de gunoi mici dimensiunea obiectelor supraviețuitoare este întotdeauna mai mare decât dimensiunea disponibile zonelor supraviețuitoare, astfel încât în ​​acest caz, putem dona distribuția corectă în favoarea dimensiunii eden spațiu:


Principiile de bază ale configurării colecției de gunoi de la zero


Ca rezultat, am reușit să reducem mărimea pauzei totale de la 3.227 s până la 1.481 s pentru 30 de secunde din experiment, în timp ce crește ușor consumul total de memorie. Un lot sau un pic - depinde de caracteristicile specifice, în special, având în vedere tendința de a reduce costul de memorie fizică și principiul maximizării utilizarea memoriei - este important să se găsească un echilibru între diferitele zone ale GC și procesul este mai creativ decât științific.

Cu cât memoria alocată aplicației este mai mare, cu atât mai bine funcționează colecția de gunoi și cu atât sunt mai bune caracteristicile cantitative ale debitului și ale timpului de răspuns al WUT? Cu o creștere a memoriei, puteți obține o creștere semnificativă a latenței de dispersie (simplificată - răspândire). Cu o grămadă mare, timpul gc întreg cu s-t-w (wtop lume) este mai lung decât pauza, ceea ce înseamnă o creștere a latenței dacă ajunge la gc completă.

Unii tovarăși conduc jvm cu un imens șold și periodic pur și simplu repornește întreg, fără a aștepta gc completă.

De la clasici. În antipatternitățile de a folosi Apache Cassandra există o tabletă excelentă care arată ce se poate gândi prin creșterea incredibilă a lui -Xms / Xmx.


www.datastax.com/documentation/cassandra/1.2/cassandra/architecture/architecturePlanningAntiPatterns_c.html


Avem pe de o sarcină la un -Xmx de la 12G la 16G la nodul Cassandra au fost foarte lente latență, de mare, de expirări și pierderea inserțiilor la 8G totul a fost de lucru în mod constant la fluxul normal (6 nod de 500-600 MByte / s per nod pe 2x SSD în RAID1).

În unele subiect anterior am menționat acest caz, dar a existat o inexactitate. Numitul există flux (50 Mbit / s) aplicat fluxul de intrare de pe nodah la join'a cu dicționare din memorie și o denormalizare de date din fluxul de alimentare.







Articole similare

Trimiteți-le prietenilor: