Puisque Java 7 va utiliser le nouveau garbage collection G1 par défaut, Java sera-t-il capable de gérer un tas plus grand d'un ordre de grandeur sans temps de pause GC "dévastateurs" supposés? Quelqu'un a-t-il réellement mis en œuvre G1 en production, quelles ont été vos expériences?
Pour être honnête, la seule fois où j'ai vu de très longues pauses GC, c'est sur de très gros tas, bien plus qu'un poste de travail n'en aurait. Pour clarifier ma question; G1 ouvrira-t-il la porte à des tas de centaines de Go? TB?
java
garbage-collection
java-7
g1gc
Benstpierre
la source
la source
Réponses:
On dirait que le but de G1 est d'avoir des temps de pause plus petits, même au point où il a la possibilité de spécifier un objectif de temps de pause maximal.
Le ramassage des ordures n'est plus simplement une simple affaire «Hé, c'est plein, déplaçons tout en même temps et recommençons» - c'est un système de threads en arrière-plan incroyablement complexe, à plusieurs niveaux. Il peut effectuer une grande partie de sa maintenance en arrière-plan sans aucune pause, et il utilise également la connaissance des modèles attendus du système au moment de l'exécution pour aider - comme supposer que la plupart des objets meurent juste après avoir été créés, etc.
Je dirais que les temps de pause du GC vont continuer à s'améliorer, et non à empirer, avec les prochaines versions.
ÉDITER:
en relisant, il m'est venu à l'esprit que j'utilise quotidiennement Java - Eclipse, Azureus et les applications que je développe, et cela fait LONGTEMPS que je n'ai pas vu une pause. Pas une pause significative, mais je veux dire une pause du tout.
J'ai vu des pauses lorsque je clique avec le bouton droit de la souris sur l'explorateur Windows ou (occasionnellement) lorsque je connecte certains matériels USB, mais avec Java - rien du tout.
GC est-il toujours un problème avec quelqu'un?
la source
Je l'ai testé avec une application lourde: 60 à 70 Go alloués au tas, avec 20 à 50 Go en cours d'utilisation à tout moment. Avec ce type d'applications, c'est peu dire que votre kilométrage peut varier. J'exécute JDK 1.6_22 sur Linux. Les versions mineures sont importantes - avant environ 1.6_20, il y avait des bogues dans G1 qui provoquaient des NullPointerExceptions aléatoires.
J'ai trouvé qu'il est très efficace pour respecter l'objectif de pause que vous lui donnez la plupart du temps. La valeur par défaut semble être une pause de 100 ms (0,1 seconde), et je lui ai dit d'en faire la moitié (-XX: MaxGCPauseMillis = 50). Cependant, une fois qu'il manque vraiment de mémoire, il panique et effectue un garbage collection complet. Avec 65 Go, cela prend entre 30 secondes et 2 minutes. (Le nombre de processeurs ne fait probablement pas de différence; il est probablement limité par la vitesse du bus.)
Par rapport au CMS (qui n'est pas le serveur GC par défaut, mais il devrait l'être pour les serveurs Web et autres applications en temps réel), les pauses typiques sont beaucoup plus prévisibles et peuvent être beaucoup plus courtes. Jusqu'à présent, j'ai plus de chance avec CMS pour les énormes pauses, mais cela peut être aléatoire; Je ne les vois que quelques fois toutes les 24 heures. Je ne sais pas lequel sera le plus approprié dans mon environnement de production pour le moment, mais probablement G1. Si Oracle continue de le régler, je soupçonne que G1 sera finalement le gagnant clair.
Si vous n'avez pas de problème avec les garbage collors existants, il n'y a aucune raison d'envisager G1 pour le moment. Si vous exécutez une application à faible latence, telle qu'une application GUI, G1 est probablement le bon choix, avec MaxGCPauseMillis réglé très bas. Si vous exécutez une application en mode batch, G1 ne vous achète rien.
la source
Bien que je n'ai pas testé G1 en production, j'ai pensé que je dirais que les GC sont déjà problématiques pour les cas sans tas "énormes". Plus précisément, les services avec seulement, disons, 2 ou 4 concerts peuvent être gravement touchés par GC. Les GC de la jeune génération ne posent généralement pas de problème car ils se terminent en millisecondes à un chiffre (ou au plus à deux chiffres). Mais les collections d'ancienne génération sont beaucoup plus problématiques car elles prennent plusieurs secondes avec des tailles d'ancienne génération de 1 gig ou plus.
Maintenant: en théorie, le CMS peut beaucoup y aider, car il peut exécuter la plupart de ses opérations simultanément. Cependant, avec le temps, il y aura des cas où il ne pourra pas le faire et devra se rabattre sur la collection «stop the world». Et quand cela se produit (après, disons, 1 heure - pas souvent, mais encore trop souvent), eh bien, gardez vos putains de chapeaux. Cela peut prendre une minute ou plus. Ceci est particulièrement problématique pour les services qui tentent de limiter la latence maximale; au lieu de prendre, disons, 25 millisecondes pour traiter une demande, il faut maintenant dix secondes ou plus. Pour ajouter une blessure à l'insulte, les clients expireront souvent la demande et réessayeront, ce qui entraînera d'autres problèmes (alias "shit storm").
C'est un domaine dans lequel G1 espérait beaucoup aider. J'ai travaillé pour une grande entreprise qui propose des services cloud pour le stockage et l'envoi de messages; et nous ne pouvions pas utiliser CMS car bien que la plupart du temps cela fonctionnait mieux que les variétés parallèles, il y avait ces effondrements. Donc, pendant environ une heure, les choses étaient bien; et puis les choses ont frappé le ventilateur ... et parce que le service était basé sur des clusters, quand un nœud a eu des problèmes, d'autres ont généralement suivi (puisque les délais induits par GC conduisent d'autres nœuds à croire que le nœud s'est écrasé, conduisant à des réacheminements).
Je ne pense pas que GC soit un problème pour les applications, et peut-être que même les services non groupés sont moins souvent affectés. Mais de plus en plus de systèmes sont regroupés (en particulier grâce aux magasins de données NoSQL) et la taille des tas augmente. Les GC OldGen sont super-linéairement liés à la taille du tas (ce qui signifie que doubler la taille du tas fait plus que doubler le temps GC, en supposant que la taille de l'ensemble de données en direct double également).
la source
Le CTO d'Azul, Gil Tene, a un bon aperçu des problèmes associés à la récupération de place et un examen de diverses solutions dans sa présentation Comprendre la récupération de place Java et ce que vous pouvez faire à ce sujet , et il y a des détails supplémentaires dans cet article: http: // www.infoq.com/articles/azul_gc_in_detail .
Le garbage collector C4 d'Azul dans notre JVM Zing est à la fois parallèle et simultané et utilise le même mécanisme GC pour les nouvelles et anciennes générations, fonctionnant simultanément et compactant dans les deux cas. Plus important encore, C4 n'a pas de solution de secours pour arrêter le monde. Tout le compactage est effectué en même temps que l'application en cours d'exécution. Nous avons des clients exécutant de très gros volumes (des centaines de Go) avec des temps de pause GC dans le pire des cas <10 msec, et selon l'application, souvent moins de 1 à 2 msec.
Le problème avec CMS et G1 est qu'à un moment donné, la mémoire de tas Java doit être compactée, et ces deux garbage collector stop-the-world / STW (c'est-à-dire interrompent l'application) pour effectuer le compactage. Ainsi, bien que CMS et G1 puissent supprimer les pauses STW, ils ne les éliminent pas. Cependant, le C4 d'Azul élimine complètement les pauses STW et c'est pourquoi Zing a des pauses GC aussi faibles, même pour des tailles de tas gigantesques.
Et pour corriger une déclaration faite dans une réponse précédente, Zing ne nécessite aucune modification du système d'exploitation. Il fonctionne comme n'importe quelle autre machine virtuelle Java sur des distributions Linux non modifiées.
la source
Nous utilisons déjà G1GC, depuis près de deux ans. Il fonctionne très bien dans notre système de traitement des transactions critiques, et il s'est avéré être un excellent support pour un débit élevé, de faibles pauses, une concurrence et une gestion optimisée de la mémoire lourde.
Nous utilisons les paramètres JVM suivants:
Actualisé
la source
Le collecteur G1 réduit l'impact des collections complètes. Si vous avez une application dans laquelle vous avez déjà réduit le besoin de collections complètes, le collecteur Concurrent map Sweep est tout aussi bon et, d'après mon expérience, il a des temps de collecte mineurs plus courts.
la source
Il semble que G1 à partir de JDK7u4 soit enfin officiellement pris en charge, voir le RN pour JDK7u4 http://www.oracle.com/technetwork/java/javase/7u4-relnotes-1575007.html .
D'après nos tests, toujours pour les grosses JVM, le CMS réglé agit toujours mieux que G1, mais je suppose qu'il se développera mieux.
la source
Récemment, j'ai été déplacé de
CMS vers G1GC avec tas 4G et processeur 8 cœurs sur les serveurs avec JDK 1.7.45 .
(JDK 1.8.x G1GC est préféré à 1.7 mais en raison de certaines limitations, je dois m'en tenir à la version 1.7.45)
J'ai configuré ci-dessous les paramètres clés et gardé tous les autres paramètres aux valeurs par défaut.
Si vous souhaitez affiner ces paramètres, consultez cet article sur oracle .
Principales observations:
Mais je suis toujours heureux que le temps de pause Max GC soit inférieur à celui de CMS. J'ai défini le temps de pause Max GC à 1,5 seconde et cette valeur n'a pas encore été franchie.
Question SE connexe:
Récupération de la mémoire Java 7 (JDK 7) et documentation sur G1
la source
CMS peut entraîner une dégradation lente des performances, même si vous l'exécutez sans accumuler d'objets permanents. Ceci est dû à la fragmentation de la mémoire que G1 est censée éviter.
Le mythe sur G1 disponible uniquement avec un support payant n'est que cela, un mythe. Sun et maintenant Oracle ont clarifié cela sur la page JDK.
la source
G1 GC est censé fonctionner mieux. Mais si le réglage -XX: MaxGCPauseMill est trop agressif, les déchets seront collectés trop lentement. Et c'est pourquoi le GC complet s'est déclenché dans l'exemple de David Leppik.
la source
Je viens d'implémenter G1 Garbage Collector dans notre projet Terracotta Big Memory. Tout en travaillant sur différents types de collecteurs, G1 nous a donné les meilleurs résultats avec un temps de réponse inférieur à 600 ms.
Vous pouvez trouver les résultats des tests (26 au total) ici
J'espère que ça aide.
la source
J'ai récemment migré une partie de Twicsy vers un nouveau serveur avec 128 Go de RAM et j'ai décidé d'utiliser 1.7. J'ai commencé par utiliser tous les mêmes paramètres de mémoire que ceux que j'utilisais avec 1.6 (j'ai plusieurs instances en cours d'exécution pour faire diverses choses, de 500 Mo de tas à 15 Go, et maintenant une nouvelle avec 40 Go) et cela n'a pas bien fonctionné du tout . 1.7 semble utiliser plus de tas que 1.6, et j'ai rencontré beaucoup de problèmes au cours des premiers jours. Heureusement, j'avais beaucoup de RAM pour travailler et j'ai augmenté la RAM pour la plupart de mes processus, mais j'avais encore des problèmes. Mon MO normal était d'utiliser une très petite taille de tas minimum de 16 m, même avec un tas maximum de plusieurs gigaoctets, puis d'activer le GC incrémentiel. Cela a réduit les pauses au minimum. Cela ne fonctionne pas maintenant, et j'ai dû augmenter la taille minimale à peu près à ce que je m'attendais à utiliser en moyenne dans le tas, et cela a très bien fonctionné. Le GC incrémentiel est toujours activé, mais je vais l'essayer sans. Aucune pause pour le moment et les choses semblent aller très vite. Donc, je pense que la morale de l'histoire est de ne pas vous attendre à ce que vos paramètres de mémoire se traduisent parfaitement de 1,6 à 1,7.
la source
G1 rend l'application beaucoup plus agile: la latence de l'application augmentera - l'application peut être nommée "soft-real-time". Cela se fait en remplaçant deux types d'exécutions GC (petites mineures et une grande sur Tenured Gen) par des petites de taille égale.
Pour plus de détails, consultez ceci: http://geekroom.de/java/java-expertise-g1-fur-java-7/
la source
Je travaille avec Java, pour petits et grands Heap, et la question du GC et du Full GC apparaît tous les jours, car les contraintes peuvent être plus strictes que d'autres: dans certains environnements, 0,1 seconde de scavenger GC ou Full GC, kill simplement la fonctionnalité, et avoir une configuration et une capacité à grain fin est important (CMS, iCMS, autres ... l'objectif est ici d'avoir le meilleur temps de réponse possible avec le traitement presque en temps réel (ici le traitement en temps réel est souvent de 25 ms) , donc, fondamentalement, toute amélioration de l'ergonomie et de l'heuristique du GC est la bienvenue!
la source
J'utilise G1GC sur Java 8 et aussi avec Groovy (également Java 8), et je fais différents types de charges de travail, et globalement G1GC fonctionne comme ceci:
L'utilisation de la mémoire est très faible, par exemple 100 Mo au lieu de 500 Mo par rapport aux paramètres Java par défaut
Le temps de réponse est constant et très faible
Les performances entre les paramètres par défaut et G1GC sont de 20% de ralentissement lors de l'utilisation de G1GC dans le pire des cas (sans réglage, application monothread). Ce n'est pas grand-chose compte tenu d'un bon temps de réponse et d'une faible utilisation de la mémoire.
Lors de l'exécution à partir de Tomcat qui est multi-thread, les performances globales sont 30% meilleures et l'utilisation de la mémoire est beaucoup plus faible ainsi que les temps de réponse sont beaucoup plus faibles.
Donc, dans l'ensemble, lorsque vous utilisez des charges de travail vraiment diverses, G1GC est un très bon collecteur pour Java 8 pour les applications multithreads, et même pour les applications à un seul thread, il y a certains avantages.
la source
Il n'est pas suggéré d'utiliser java8 w / G1GC pour le calcul du virgule flottante avec une JVM de type hotspot. C'est dangereux pour l'intégrité et la précision de l'application.
https://bugs.openjdk.java.net/browse/JDK-8148175
JDK-8165766
JDK-8186112
la source