Rglage des garbage collectors GC sur JDK 1
Réglage des garbage collectors (GC) sur JDK 1. 6 Exemple de la plateforme d’échanges OSB/MOM A. Dewavrin - 3 Juin 2013 1
Historique des versions Date Auteur Actions Version 03/06/2013 Anselme Dewavrin Récapitulatif du travail d’amélioration des GC de la plateforme d’échange V 0. 1 05/06/2013 Anselme Dewavrin Ajouts et conclusion V 0. 2 06/06/2013 Anselme Dewavrin Simplifications et schémas V 0. 3 A. Dewavrin 2 28/01/2011
Problématique Les JVMs* se figent régulièrement, tour-à-tour, typiquement pendant des durées de quelques secondes Conséquences : • Ces pauses peuvent provoquer des timeouts sur les appelants (Tunnel de commande, Compiere, historisation) • Suspicion de nombreux dysfonctionnements (abandon de transactions etc. ) dans le MOM et l’OSB en prod. • La moitié des trous dans l’historique Flowtracker est due à ces pauses. La cause : Un code Java ne relâche jamais la mémoire. C’est un mécanisme (garbage collector) qui fait régulièrement la récupération de la mémoire abandonnée, provoquant des pauses. *par exemple sur la plateforme d’échange, décrite en annexe A. Dewavrin 3 28/01/2011
Anatomie de la mémoire d’une JVM New (ou Young) Les objets sont créés en Eden La zone « new » est balayée par un garbage-collector (minor) qui provoque normalement des pauses courtes… …la zone « old » par un autre GC (major), le plus connu car son réglage par défaut provoque des pauses longues de la JVMs, parfois de plusieurs dizaines de secondes. On appelle cela « full garbage » . Eden S 1 Les objets ayant survécu à un ou plusieurs passages du garbage collector de la zone « new » sont placés en Survivor, alternativement S 1 et S 2 Les objets ayant survécu à de nombreux passages du garbage collector de la zone « new » sont placés en zone « old » (c’est ce qui est nommé « promotion » ) Old (ou Tenured) Les objets et métadonnées (classes, etc. ) éternels sont placés dans la zone « permanent » Perm x s s A. Dewavrin x s s Les données d’appel et retour de chaque thread sont stockées en zone « XSS » 4 28/01/2011
Activité des garbage collectors 1. L’application demande régulièrement de la mémoire mais ne la libère jamais (principe de java). La mémoire est réservée en zone « new » (précisément, en Eden) 2 2. Quand la new est pleine, un garbage de zone « new » est déclenché. 1 4 3. Dans le cas idéal tous les objets sont désormais inutilisés et la mémoire est récupérée New 4. Quand l’application est plus chargée, la new se remplit plus vite et les garbages new sont plus fréquents 5 3 5. Quand il reste des objets encore utilisés, le garbage ne peut pas récupérer leur mémoire, il les laisse en new mais les déplace dans une des zones « survivor » 6 7 6. Quand des objets ont survécu à plusieurs garbages, ils sont considérés comme durables, et sont promus en zone « Old » ce qui leur évite d’être scannés tout le temps pour rien par le garbage de zone « new » . 7. Quand la zone « old » est remplie, un garbage « full » se déclenche et récupère la mémoire des objets inutilisés. Par défaut cela provoque une pause (nommée « stop-theworld » ) Old 8. Le niveau atteint après un garbage full donne une idée de la mémoire minimum nécessaire à l’application. Il ne reste que les objets très durables. Si trop peu de mémoire est récupérée on a un out-of-memory de type « java heap» . Si la JVM passe plus de 99% de son temps à faire du garbage on a un out-of-memory de type «GC overhead limit » 8 A. Dewavrin 5 28/01/2011
Logs de l’activité des garbage collectors Il est possible (souhaitable) de demander au garbage de logger son activité. Voici ce qu’on y voit : {Heap before GC invocations=7791 (full 39): par new generation total 917504 K, used 867685 K [0 x 0000000714400000, 0 x 0000000754400000) eden space 786432 K, 100% used [0 x 0000000714400000, 0 x 0000000744400000) from space 131072 K, 61% used [0 x 000000074 c 400000, 0 x 0000000751359768, 0 x 0000000754400000) to space 131072 K, 0% used [0 x 0000000744400000, 0 x 000000074 c 400000) concurrent mark-sweep generation total 2097152 K, used 1750952 K [0 x 0000000754400000, 0 x 00000007 d 4400000) concurrent-mark-sweep perm gen total 716800 K, used 276326 K [0 x 00000007 d 4400000, 0 x 0000000800000000) Le remplissage des zones survivor est 218751. 537: [GC 218751. 537: [Par. New indiqué en tant que « from » et « to » Desired survivor size 67108864 bytes, new threshold 15 (max 15) - age 1: 8197912 bytes, 8197912 total L’âge maximum avant de passer - age 2: 5748856 bytes, 13946768 total - age 3: 513544 bytes, 14460312 total en zone « old » - age 4: 845536 bytes, 15305848 total - age 5: 799008 bytes, 16104856 total - age 6: 514008 bytes, 16618864 total Les objets du survivor, ayant survécu à 1 ou - age 7: 6038896 bytes, 22657760 total plusieurs garbages de la zone « new » , - age 8: 6732456 bytes, 29390216 total peuvent être indiqués sur demande dans le - age 9: 8004688 bytes, 37394904 total - age 10: 4099760 bytes, 41494664 total log gc (paramètre print. Tenuring. Distribution). - age 11: 4469168 bytes, 45963832 total - age 12: 51968 bytes, 46015800 total Ici, après 15 ils seront déplacés en zone - age 13: 4498888 bytes, 50514688 total - age 14: 76408 bytes, 50591096 total « old » . C’est la « promotion » . - age 15: 558072 bytes, 51149168 total : 867685 K->61866 K(917504 K), 0. 1913490 secs] 2618638 K->1812977 K(3014656 K), 0. 1925590 secs] [Times: user=0. 55 sys=0. 01, real=0. 20 secs] La durée de la pause causée par le GC Heap after GC invocations=7792 (full 39): par new generation total 917504 K, used 61866 K [0 x 0000000714400000, 0 x 0000000754400000) eden space 786432 K, 0% used [0 x 0000000714400000, 0 x 0000000744400000) from space 131072 K, 47% used [0 x 0000000744400000, 0 x 000000074806 a 930, 0 x 000000074 c 400000) to space 131072 K, 0% used [0 x 000000074 c 400000, 0 x 0000000754400000) concurrent mark-sweep generation total 2097152 K, used 1751111 K [0 x 0000000754400000, 0 x 00000007 d 4400000) concurrent-mark-sweep perm gen total 716800 K, used 276326 K [0 x 00000007 d 4400000, 0 x 0000000800000000) } A. Dewavrin 6 28/01/2011
Démographie et réglages de la zone « survivor » Eden Age 1 Age 2 Age 3 Age 4 Age 5 Age 6 Age 7 Age 8 Age 9 Age 10 … Age 15 Eden Situation idéale : à la fin de la maturation, il reste en survivor uniquement les objets durables. Seuls ceuxlà seront promus en old. Old Eden Le process de maturation (tenuring) est trop court. Trop d’objets sont copiés en old alors qu’ils vont mourir peu après. Cela provoque un remplissage inutile de la old et des garbages plus fréquents, et donc plus de pauses. L’âge maxi en survivor est trop grand, on pourrait promouvoir plus vite les objets en old pour leur éviter d’être scannés de nombreuses fois pour rien par le garbage collector de la zone « New » . A gauche, le cas d’une charge régulière, à droite une charge par à-coups Paramètre : Survivor. Ratio Old Paramètre : Max. Tenuring. Threshold A. Dewavrin 7 28/01/2011
Réglages de la zone « new » Eden Le Eden est trop court. En l’agrandissant un peu on y aurait laissé mourir les objets les plus éphémères, évitant une copie pour rien d’un grand nombre d’objets dans les premiers âges des survivors Situation idéale Age 1 Age 2 Age 3 Age 4 Age 5 Age 6 Age 7 Age 8 Age 9 Age 10 … Age 15 Paramètre : New. Ratio ou New. Size Old A. Dewavrin Old 8 28/01/2011
Proportions de la mémoire d’une JVM New (ou Young) New. Ratio Rapport entre Old et New. Typiquement 2 Eden S 1 S 2 Xmx (le « heap » ) Typiquement 2 G Survivor. Ratio Rapport entre Eden et un Survivor. Typiquement 6 car on observe qu’un objet sur 6 n’est pas éphémère Old (ou Tenured) Perm. Size Typiquement 0. 5 à 1 G Suivant la complexité de l’application (nb de classes) Perm x s s A. Dewavrin x s s Xss Taille de la stack d’une thread. Laisser par défaut sauf si erreurs « stack overflow » 9 28/01/2011
Pauses d’une application java Une application Java fait des pauses, c’est un fait. Pour les minimiser il faut éviter les promotions inutiles vers la zone « Old » . Et quand c’est impossible, on abandonnera le garbage collector de zone « Old » par défaut pour utiliser au choix CMS ou parallèle. Choisi A. Dewavrin Type de GC Old avantages Inconvénients Par défaut Efficacité CPU et RAM. Pauses longues Conçu pour les machines monoprocesseur. CMS Pauses très réduites Fragmentation de la mémoire java Parallèle Pauses réduites inefficacité CPU. La parallélisation sur 4 procs n’apporte qu’une réduction par 2 des pauses 10 28/01/2011
Détection des pauses d’une application java Quand on suspecte une application de faire des pauses longues dues à sa gestion de mémoire (temps de réponses de temps en temps beaucoup plus grands, attente hors charge avec un cpu à 100%), on activera le log de l’activité du garbage collector avec les paramètres de lancement suivants : -verbose: gc -XX: +Print. GCDetails -XX: +Print. GCTime. Stamps -XX: +Print. Heap. At. GC -Xloggc: chemin/gc. log Ensuite après de l’activité, on pourra recher dans le fichier le mot « real » avec par exemple la commande : grep real gc. log Pauses du GC de zone « New » : : 864576 K->92106 K(917504 K), 0. 2122710 secs] 2330426 K->1560757 K(3014656 K), 0. 2134260 secs] [Times: user=0. 62 0. 22 secs] sys=0. 00, real= Pauses du GC de zone « Old » (full GC): 15423. 664: [Full GC [PSYoung. Gen: 10981 K->0 K(950016 K)] [PSOld. Gen: 2068450 K->967902 K(2097152 K)] 2079431 K->967902 K(3047168 K) [PSPerm. Gen: 266201 K->266201 K(716800 K)], 4. 5992780 secs] [Times: user=4. 59 sys=0. 01, real=4. 60 A. Dewavrin 11 secs] 28/01/2011
Diminution des pauses d’une JVM 1 New pause 0. 4 s Zone « new » : La parallélisation est possible sur les machines multicoeurs. Il y a toujours des pauses, mais plus courtes. 2 1. Réglage par défaut 2. Réglage parallèle. Paramètres : « Use. Par. New. GC » « Parallel. GCThreads =4 » pause 0. 1 s 4 3 Old pause 0. 5 s (remark) pause 8 s A. Dewavrin pause 1 s (initial mark) 12 Zone « old » : L’utilisation d’un algorithme concurrent (qui se déroule en grande partie en même temps que l’application), permet de limiter les « stop-theworld » 3. Réglage par défaut 4. Réglage CMS. Paramètres : « Use. Conc. Mark. Sweep. GC » 28/01/2011
Mesure de la réduction des pauses Après changement des réglages, on relancera les mesures. Zone « New » : grep real gc. log : 817350 K->90921 K(917504 K), 0. 1499620 secs] 817350 K->90921 K(3014656 K), 0. 1500920 secs] [Times: user=0. 51 0. 15 secs] sys=0. 05, real= Zone « Old » Comme on a mis en place le CMS, il faut uniquement prendre en compte les phases « initial mark » et « remark » , les seules qui gèlent la JVM. On voit que les pauses ont été raccourcies grep remark|initial gc. log 305062. 563: [GC [1 CMS-initial-mark: 1791541 K(2097152 K)] 1929285 K(3014656 K), 0. 3005340 secs] [Times: 0. 30 secs] user=0. 29 sys=0. 01, real= 302772. 317: [GC[YG occupancy: 519538 K (917504 K)]302772. 317: [Rescan (parallel) , 0. 4999590 secs]302772. 817: [weak refs processing, 0. 0030560 secs] [1 CMS-remark: 1982935 K(2097152 K)] 2502474 K(3014656 K), 0. 5036940 0. 51 secs] [Times: user=1. 34 sys=0. 01, real= A. Dewavrin 13 28/01/2011
Causes d’échec du CMS Deux cas peuvent provoquer un échec du CMS, ce qui n’est pas grave mais conduit à un GC classique, et donc une pause longue. Type d’échec Cause Fragmentation de la zone « Old » Promotion impossible de la New vers la Old. En effet le CMS ne défragmente pas la mémoire, formant un gruyère avec des trous de plus en plus petits. Les gros objets ne peuvent plus être promus Urgence A. Dewavrin Une accélération de l’activité rend improbable de finir à temps le garbage full en mode concurrent. Le CMS compare de temps qu’il lui faudra au temps qu’il reste avant que la zone « Old » ne soit pleine. Il peut alors décider de faire un GC classique dans le but de geler la JVM, arrêtant ainsi le remplissage. schéma ! ? détection Comment éviter grep fail gc. log En dev : on évitera de manipuler de gros objets longtemps. 214371. 138: [GC 214371. 138: [Par. New (promotion failed) grep fail gc. log ! ? 14 (concurrent mode failure): 1942604 K>1301745 K(2097152 K), 15. 0272900 secs] 2835325 K>1301745 K(3014656 K), [CMS Perm : 281374 K>275121 K(716800 K)], 16. 8480540 secs] [Times: user=14. 61 sys=0. 11, real=16. 85 secs] En prod : on mettra plus de Old En dev : on évitera les gros objets En prod On évitera les promotions inutiles (réglage eden et survivors) on déclenchera plus tôt le CMS au moyen du paramètre CMSInitiating. Occupan cy. Fraction (80% à 92% par défaut). 28/01/2011
Dimensionnement RAM des machines Méthode théorique Il faut calculer : heap + perm + nb_threads * profondeur d’appels + empreinte fichiers ouverts Et ajouter l’OS, les autres applications (easytrust, omnivision, tivoli, etc. ), des caches et buffers disque. Méthode itérative: 1. On choisi une des configurations typiques : 2. On ajuste la mémoire heap des JVMS en fonction du niveau bas du Old (après un GC full). On règle le « Old » à deux ou trois fois le niveau bas. 3. On surveille le swapping au moyen des colonnes « si » et « so » de vmstat (et non pas sur la commande free comme le fait Tivoli actuellement). Si ça swappe il faut ajouter de la RAM ou diminuer les JVMs (swapper est plus grave que garbager souvent). A. Dewavrin 15 28/01/2011
Conclusions 1. Malheureusement il n’existe pas de réglage universel car chaque application est différente en termes : Ù d’utilisation de la mémoire (nombre et longévité des objets utilisés) Ù d’attendus (latence acceptée, temps de calcul maximum) Ù d’infrastructure utilisée (mémoire disponible de la machine, nombre de cpus…) 2. Pour le GC « major » , c’est-à-dire de la zone « old » , il faut accepter un défaut, au choix: Ù forte utilisation du cpu (GC parallèle) Ù longues pauses (GC classique) Ù fragmentation de la mémoire nécessitant un petit surdimensionnement (GC CMS) 3. Le réglage suivant choisi pour la plateforme d’échange a divisé les pauses par 10 au moins : Ù GC minor en parallèle, GC major en CMS Ù heap de 2 Go, new de 1/3, survivors de 1/6 Ù Seul l’OSB a pour l’instant été laissé à 3 Go suite à un incident. Ù On a encore des pauses de temps en temps, dues à la fragmentation (20 fois moins). 4. Des bonnes pratiques de développement (attention aux instanciations inutiles ou implicites) peuvent être promues, mais dans le cas de progiciels c’est parfois difficile à imposer. Il ne reste alors que le tuning technique pour faire fonctionner l’appli. 5. Le futur algorithme de garbage (G 1) est prometteur, il faudra l’évaluer avec java 7. A. Dewavrin 16 28/01/2011
Annexe : Plateforme d’échanges (production) • Une cinquantaine de JVMs en weblogic 10. 3. 4 / 10. 3. 6 • Basées sur le jdk 1. 6 de Sun A. Dewavrin 17 28/01/2011
Sources Ù Ù Ù Ù http: //www. javaworld. com/javaworld/jw-01 -2002/jw-0111 -hotspotgc. html http: //artiomg. blogspot. fr/2012/06/tracking-excessive-garbage-collection. html http: //blog. ragozin. info/2011/10/java-cg-hotspots-cms-and-heap. html http: //lokeshtc. blogspot. fr/2012/11/jvm-heap-tuning-on-sun-jdk-using-cms. html dewavrin@yahoo. com / adewavrin@itboosters. fr http: //blog. mgm-tp. com/2013/03/garbage-collection-tuning/ http: //java. dzone. com/articles/how-tame-java-gc-pauses http: //www. slideshare. net/ludomp/gc-tuning-in-the-hotspot-java-vm-a-fisl-10 -presentation A. Dewavrin 18 28/01/2011
- Slides: 18