Tuning JVM (GC) pour la haute réactif serveur d'application
Je suis en cours d'exécution d'une application serveur sur Linux 64 bits avec 8 Processeurs core et 6 GO de mémoire.
Le serveur doit être très réactive.
Après quelques inspection, j'ai trouvé que l'application en cours d'exécution sur le serveur crée plutôt une énorme quantité d'objets éphémères, et ne dispose que d'environ 200~400 MO longue durée de vie des objets(tant qu'il n'y a pas de fuite de mémoire)
Après la lecture de http://java.sun.com/javase/technologies/hotspot/gc/gc_tuning_6.html
J'utilise ces options JVM
-server -Xms2g -Xmx2g -XX:MaxPermSize=256m -XX:NewRatio=1 -XX:+UseConcMarkSweepGC
Résultat: le mineur GC 0.01 ~ 0.02 sec, les principaux GC 1 ~ 3 sec
le mineur GC arrive constamment.
Comment puis-je améliorer ou régler la JVM?
plus grande taille de segment de mémoire? mais ça va prendre plus de temps pour la GC?
plus NewSize et MaxNewSize (pour les jeunes générations)?
autres collecteur? en parallèle GC?
est-ce une bonne idée de laisser les grands GC lieu le plus souvent? et comment?
Vous devez vous connecter pour publier un commentaire.
Sauf si vous déclarez des pauses, je dirais que le CMS collector est en train de faire ce que vous avez demandé de le faire. Par définition, CMS utiliser un plus grand pourcentage de la CPU de la Série et en Parallèle les collectionneurs. C'est la peine de vous payer pour de faibles temps de pause.
Si vous voyez de 1 à 3 seconde pause fois, je dirais que vous avez besoin de faire quelques réglages. Je ne suis pas expert, mais il semble que vous devriez commencer par la réduction de la valeur de
CMSInitiatingOccupancyFraction
à partir de la valeur par défaut de 92.L'augmentation de la taille de segment de mémoire permettra d'améliorer le "débit" de la GC. Mais si votre problème est de longues pauses, l'augmentation de la taille de segment de mémoire est susceptible d'aggraver le problème.
CMSInitiatingOccupancyFraction
valeur par défaut est -1 et cms utiliserCMSTriggerRatio
dont la valeur par défaut est 80 .Attention .... GC peut être un poilu sujet si vous n'êtes pas prudent. Dans tout runtime (JVM pour Java /CLR pour .Net), il existe plusieurs processus qui ont lieu. Généralement, il y a un stade précoce de l'optimisation de la mémoire (les Jeunes Générations de Collecte des Ordures et les Jeunes Gen GC & les Anciennes Générations de Collecte des Ordures /Old Gen GC). Le jeune gen gc qui se passe sur une base régulière et est communément attribuée à vos petites pauses /le hoquet. L'ancienne gen gc est normalement ce qui se passe quand vous voyez le long de "stop the world" pauses.
Pourquoi, vous pourriez demander? La raison pour laquelle vous obtenez des pauses de votre runtime /JVM est que lorsque le moteur d'exécution ne son de nettoyage de la masse, il doit passer par ce qu'on appelle un changement de phase. Il arrête les threads s'exécutant votre application dans le but de marquer et de swap de pointeurs pour optimiser votre mémoire disponible. Yong gen est plus rapide mais il est principalement libérant des objets qui ne sont que temporaires. Old gen, cependant, évalue tous les objets sur le tas et quand vous êtes à court de mémoire, il donnera un coup de pied de libérer de beaucoup de mémoire nécessaire.
Pourquoi la Prudence? Old gen obtient de façon exponentielle pire, dans des temps de pause plus de tas que vous utilisez. en 2 à 4 GO au total, la taille du segment, vous devez être bien sur moderne runtimes comme la version 6 de Java (JDK 1.6+). Une fois que vous allez au-delà de cette threashold vous verrez un accroissement exponentiel des temps de pause. J'ai des clients qui ont de redémarrer les serveurs - comme dans certains rares cas où un segment de mémoire est grande GC des temps de pause plus longue qu'un redémarrage complet.
Il y a quelques nouveaux outils qui sont assez cool et peut vous donner une pointe sur l'évaluation si GC est votre douleur. JHiccup est un et il est libre à partir du azulsystemssite web. À ce moment, je pense que c'est uniquement pour le bien Linux. Ils ont aussi une machine qui a une re-construit GC algorithme qui s'exécute pauseless ... mais si vous êtes sur un seul serveur de déploiement, avec une non-critique de l'app, il peut ne pas être rentable (que l'on n'est pas libre).
Pour résumer, si votre exécution /JVM /CLR tas est inférieure à 2 GO, l'ajout de mémoire aidera. Soyez sûr de vous donner une surcharge. Vous ne voulez jamais atteint 100% de la taille du Segment de mémoire de taille si possible. C'est alors que les longues pauses sont plus longues. Donnez-vous un supplément de 20%+ de la mémoire sur ce que vous pensez que vous aurez besoin. De cette façon, vous avez de la place pour la table des algorithmes pour déplacer les objets à des fins d'optimisation. Si jamais vous prévoyez d'aller grand ... il y a un outil qui résout le circa 1990 JVM de la technologie (Azul Systèmes Zing JVM), mais il n'est pas libre. Ils offrent un outil open source pour diagnostiquer GC questions. La JVM (ce que j'ai essayé) dispose également d'un vraiment cool thread visibilité au niveau de l'outil qui vous permet de faire rapport sur toutes les fuites, de bogues, ou des serrures dans la production sans surcharge (une astuce avec le déchargement des données de la JVM traite déjà avec horodatage). Qui a sauvé des tonnes de dev temps de test ... mais encore une fois, pas pour les petites applications.
Rester en-dessous de 4 GO. Donner de la marge supplémentaire. Et si vous voulez, vous pouvez tourner sur ces indicateurs pour surveiller GC pour Java /JVM:
Vous pouvez essayer quelques-uns des autres collectionneurs Hotspot utilise. Il y a plus d'un.
Si vous êtes sur Linux, aller de l'avant et essayer de le JHiccup outil. Il est libre.
Vous pouvez être intéressé à essayer de la basse-pause Garbage-Premier collectionneur à la place du concurrent mark-sweep (même si c'est pas forcément le plus performant pour toutes les collections, il est censé avoir un meilleur pire des cas). Elle est activée par
-XX:+UseG1GC
et est censé pour être vraiment awesomesauce, mais vous pouvez lui donner une évaluation approfondie avant de l'utiliser en production. Il a probablement amélioré depuis, mais il semble avoir été un peu buggy il y a un an, comme on le voit dans Expérience avec JDK 1.6.x G1 (“Garbage First”)Il est parfaitement bien pour la collecte des ordures pour s'exécuter en parallèle avec votre programme, si vous avez beaucoup de cpu, ce que vous faites.
Ce que vous voulez, c'est à faire absolument certain que vous ne sera pas exécuté dans un scénario où la collecte des ordures PAUSE votre programme principal.
Avez-vous essayé tout simplement pas en indiquant tous les indicateurs, sauf pour dire que vous souhaitez que le serveur VM (pour la JVM de Sun), puis de mettre votre serveur sous une lourde charge pour voir comment il se comporte? Alors seulement vous pouvez le voir, si vous avez des améliorations à partir de bricolage avec des options.
Cela sonne comme un débit d'application et doit probablement utiliser le débit du collecteur. Je serait un équilibre entre la taille de la nouvelle gen rendant assez grand pour ne pas GC, trop souvent, et assez petit pour éviter de longues pauses. 20ms sonne comme une longue mineure GC pour moi. Je soupçonne aussi votre survivant de l'espace est trop grand et vient juste d'être gaspillée. Si vous n'avez pas beaucoup de survivants à old gen, vous ne devriez pas avoir autant de survivre à vos petits GCs.
En fin de compte, vous devez utiliser jvmstat et VisualGC pour vraiment avoir une idée de la façon dont votre application à l'aide de la mémoire.
Pour la haute réactif application serveur, je pense que vous voulez voir les grandes GC arrive de moins en moins fréquemment. Voici la liste des paramètres de l'aide.
-XX:+CMSParallelRemarkEnabled
-XX:+CMSScavengeBeforeRemark
-XX:+UseCMSInitiatingOccupancyOnly
-XX:CMSInitiatingOccupancyFraction=50
-XX:CMSWaitDuration=300000
-XX:GCTimeRatio=40
Plus grande taille de segment de mémoire ne peut pas aider sur le bas de la pause, aussi longtemps que votre application ne permet pas de manquer de mémoire.
Plus NewSize et MaxNewSize aiderait sur le débit, ne peut pas aider sur le bas de la pause. Si vous choisissez de prendre cette approche, vous pouvez envisager de donner GC threads plus de temps d'exécution par paramètre -XX:GCTimeRatio inférieur. Le point est de se rappeler de prendre une approche holistique lors de l'optimisation de la JVM.
Je pense que les précédentes affiches ont manqué quelque chose de très évident - la Perm Génération taille est trop faible. Si le système utilise de 200 à 400 MO comme la génération permanente -, alors il peut être préférable de fixer Max Perm Gen à 400 MO. le PerGen taille doit également être réglé sur la même valeur. Il vous sera alors de ne jamais manquer de Génération Permanente de l'Espace.
Actuellement, il ressemble à la JVM a passer beaucoup de temps à déplacer des objets dans et hors de la Génération Permanente. Cela peut prendre du temps. JVM essaie d'allouer de la mémoire contiguë zones à des Objets Java - ce des vitesses d'accès à la mémoire en raison de matériel au niveau des fonctionnalités. Pour ce faire, il est très utile d'avoir beaucoup de mémoire tampon. Si la Génération Permanente est presque plein, la découverte de nouveaux objets permanents doivent être séparés ou objets existants doivent être mélangées. C'est ce qui déclenche un full GC, ainsi que les causes de long plein GC pauses.
La question stipule que la Génération Permanente de taille a déjà été mesuré - si cela n'a pas été fait, il doit être mesuré à l'aide d'un outil. Ces outils processus de logs générés par la JVM avec le verboseGC option est activée.
La marque et de balayer les options énumérées ci - dessus peuvent ne pas être nécessaires à cette amélioration.
Les gens jettent des GC options comme des solutions sans en évaluer la maturité qu'ils ont prouvé pour être dans l'utilisation réelle.