92 votes

Java G1 garbage collection en production

Étant donné que Java 7 va utiliser la nouvelle collecte de déchets G1 par défaut, Java va-t-il être capable de gérer un tas plus important sans les temps de pause GC supposés "dévastateurs" ? Quelqu'un a-t-il déjà mis en œuvre G1 en production et quelles ont été ses expériences ?

Pour être juste, la seule fois où j'ai vu des pauses GC vraiment longues, c'est sur des tas très importants, bien plus que ce qu'une station de travail pourrait avoir. Pour clarifier ma question, G1 ouvrira-t-il la porte à des tas de plusieurs centaines de Go ? TB ?

16 votes

Même si elle pourrait être reformulée de manière plus précise, cette question n'est pas horrible. J'aimerais vraiment que les gens aient à s'expliquer mieux que "Pas une question" lorsqu'ils votent pour fermer.

0 votes

Je n'ai pas voté pour la fermeture, mais j'aurais aimé que le PO fasse un travail plus objectif en détaillant ses griefs avec le CG actuel. De plus, "Java" est un langage alors qu'il parle d'une implémentation, et je ne sais pas ce que signifie "implémenter G1 en production", surtout avec le futur du reste de la question. Si cela doit être dans Java 7, personne ne l'a sûrement utilisé en production ?

6 votes

@Pascal G1 est une fonctionnalité expérimentale disponible dans le JDK depuis la mise à jour 14 du JDK 6. Par "implémenter G1 en production", je pense qu'il voulait dire l'utiliser réellement, ce n'est pas si difficile à comprendre. Et si je suis d'accord pour dire que G1 fait partie du JDK 7, et non de Java, une recherche de Java 7 sur Google renvoie la page d'accueil du JDK 7 comme premier résultat, et les deux termes sont souvent utilisés de manière interchangeable. @Benju Je ne ferais pas confiance aux résultats obtenus avec G1 sur le JDK actuel car il est expérimental, beaucoup de choses pourraient changer d'ici la version officielle.

58voto

David Leppik Points 1274

Je l'ai testé avec une application lourde : 60-70 Go alloués au tas, avec 20-50 Go utilisés à tout moment. Avec ce genre d'applications, c'est un euphémisme de dire que votre kilométrage peut varier. J'utilise le JDK 1.6_22 sur Linux. Les versions mineures sont importantes - avant la 1.6_20, il y avait des bogues dans G1 qui provoquaient des NullPointerExceptions aléatoires.

J'ai trouvé qu'il est très bon pour rester dans la cible 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 demandé d'en faire la moitié (-XX:MaxGCPauseMillis=50). Cependant, dès qu'il n'a plus beaucoup de mémoire, il s'affole et fait une collecte de mémoire complète. Avec 65 Go, cela prend entre 30 secondes et 2 minutes (le nombre de CPU ne fait probablement pas de différence ; c'est probablement limité par la vitesse du bus).

Par rapport au CMS (qui n'est pas le GC par défaut du serveur, mais qui 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 rendues 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 par 24 heures. Je ne suis pas sûr de savoir lequel sera le plus approprié dans mon environnement de production pour le moment, mais probablement G1. Si Oracle continue à l'améliorer, je pense que G1 finira par l'emporter.

Si vous n'avez pas de problème avec les garbage collectors existants, il n'y a aucune raison d'envisager G1 pour le moment. Si vous exécutez une application à faible latence, comme 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 apporte rien.

34voto

Bill K Points 32115

Il semble que l'objectif de G1 soit de réduire les temps de pause, au point de pouvoir spécifier un objectif de temps de pause maximum.

La collecte des déchets n'est plus un simple "Hé, c'est plein, déplaçons tout d'un coup et recommençons", c'est un système complexe, multi-niveaux et threadé en arrière-plan. Il peut faire 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 l'aider - comme supposer que la plupart des objets meurent juste après avoir été créés, etc.

Je dirais que les temps de pause de la GC vont continuer à s'améliorer, et non à se détériorer, avec les prochaines versions.

EDIT :

En relisant, je me suis rendu compte que j'utilise Java quotidiennement - Eclipse, Azureus et les applications que je développe - et cela fait longtemps que je n'ai pas vu de pause. Pas une pause significative, mais je veux dire une pause tout court.

J'ai vu des pauses lorsque je clique avec le bouton droit de la souris dans l'explorateur Windows ou (occasionnellement) lorsque je branche certains matériels USB, mais avec Java aucune.

Le GC est-il toujours un problème pour quelqu'un ?

0 votes

Je suis d'accord - les seules fois où j'ai vu des pauses GC, c'est quand je les ai délibérément ou accidentellement provoquées avec du code massivement parallèle qui crée des déchets......

28 votes

Oui, la GC est toujours un problème lorsque l'on commence à traiter de grands tas (>16GB), en particulier avec de grandes générations permanentes.

2 votes

@the-alchemist wow, j'ai vu votre commentaire en passant plusieurs fois et ça m'a juste frappé que vous ayez dit 16 GB ! !! Bien que je sois absolument sûr que vous avez raison de dire que cela peut entraîner des retards énormes, je veux vérifier que vous avez désactivé TOUT le swapping. Sur un système à grande mémoire, tout Le swapping de java va absolument tuer votre système (parce que GC est très peu favorable au swap). Je suis sûr que vous l'avez déjà fait, mais je voulais juste le mentionner - parce que cela ferait une énorme différence. Je n'ai jamais vu un PC avec autant de RAM - combien en avez-vous ? 32g ?

14voto

StaxMan Points 34626

Bien que je n'aie pas testé G1 en production, j'ai pensé commenter que les GC sont déjà problématiques pour les cas sans "humongous" heaps. Plus précisément, les services avec seulement, disons, 2 ou 4 gigas peuvent être sévèrement impactés par les GC. Les GC de la jeune génération ne sont généralement pas problématiques car ils se terminent en millisecondes à un chiffre (ou au plus à deux chiffres). Mais les collectes 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 giga ou plus.

En théorie, le CMS peut être d'une grande aide dans ce domaine, car il peut exécuter la plupart de ses opérations simultanément. Cependant, au fil du temps, il y aura des cas où il ne pourra pas le faire et devra se rabattre sur la collecte "arrêter le monde". Et lorsque cela se produit (après, disons, 1 heure -- pas souvent, mais toujours trop souvent), eh bien, accrochez-vous à vos chapeaux. Cela peut prendre une minute ou plus. Cela est particulièrement problématique pour les services qui essaient de limiter la latence maximale ; au lieu de prendre, disons, 25 millisecondes pour servir une requête, il faut maintenant dix secondes ou plus. Pour ajouter l'insulte à l'injure, les clients vont souvent interrompre la demande et la réessayer, ce qui entraîne d'autres problèmes (alias "tempête de merde").

C'est un domaine où l'on espérait que G1 serait d'une grande aide. Je travaillais pour une grande entreprise qui offre des services en nuage pour le stockage et la répartition des messages ; et nous ne pouvions pas utiliser CMS car, bien que la plupart du temps il fonctionnait mieux que les variétés parallèles, il avait ces fusions. Ainsi, pendant environ une heure, les choses se sont bien passées, puis les choses se sont emballées... et comme le service était basé sur des grappes, lorsqu'un nœud avait des problèmes, les autres suivaient généralement (puisque les délais d'attente induits par la GC faisaient croire aux autres nœuds que le nœud s'était écrasé, ce qui entraînait des réacheminements).

Je ne pense pas que GC soit un problème pour les applications, et peut-être même que les services non groupés sont moins souvent affectés. Mais de plus en plus de systèmes sont mis en cluster (notamment grâce aux magasins de données NoSQL) et la taille des tas augmente. Les GC d'OldGen sont liés de façon super-linéaire à la taille du tas (ce qui signifie que doubler la taille du tas fait plus que doubler le temps de GC, en supposant que la taille de l'ensemble de données en direct double également).

13voto

Scott Sellers Points 211

Gil Tene, directeur technique d'Azul, donne un bon aperçu des problèmes liés au Garbage Collection et passe en revue les différentes solutions dans son article intitulé "Garbage Collection". Comprendre la collecte d'ordures de Java et ce que vous pouvez faire à ce sujet et vous trouverez 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 concurrent, et utilise le même mécanisme GC pour la nouvelle et l'ancienne génération, travaillant simultanément et compactant dans les deux cas. Plus important encore, C4 n'a pas de solution de repli "stop-the-world". Tout le compactage est effectué en même temps que l'application en cours d'exécution. Nous avons des clients qui exécutent de très gros fichiers (des centaines de Go) avec des temps de pause GC inférieurs à 10 msec, et selon l'application, souvent inférieurs à 1-2 msec.

Le problème avec CMS et G1 est qu'à un moment donné, la mémoire du tas de Java doit être compactée, et ces deux ramasseurs de déchets arrêtent le monde/STW (c'est-à-dire mettent l'application en pause) pour effectuer le compactage. Ainsi, si CMS et G1 peuvent repousser les pauses STW, ils ne les éliminent pas. Le C4 d'Azul, en revanche, élimine complètement les pauses STW et c'est pourquoi Zing a des pauses GC si faibles, même pour des tas de taille gigantesque.

Et pour corriger une affirmation faite dans une réponse précédente, Zing ne nécessite aucune modification du système d'exploitation. Il fonctionne comme toute autre JVM sur des distributions Linux non modifiées.

3 votes

Je me demande simplement comment le C4 d'Azul a réalisé ce que vous avez dit et pourquoi Sun ou Oracle ne peuvent pas le faire. Y a-t-il un grand secret ou est-ce simplement une sorte de compromis ?

5 votes

Le C4 d'Azul possède une technologie unique qui trouve son origine dans les appliances de calcul d'Azul (qui utilisent des processeurs spécialisés conçus pour exécuter des applications Java d'entreprise) et qui a évolué pour fonctionner sur des serveurs x86 ordinaires fonctionnant sous Linux. Tous les autres garbage collectors de classe entreprise (qu'ils soient d'Oracle ou d'IBM) doivent à un moment ou à un autre faire des pauses "stop-the-world" - l'attribut unique du C4 d'Azul est qu'il ne fait jamais ces pauses STW problématiques. Si vous êtes curieux, les inventeurs du collecteur C4 ont publié un article sur son fonctionnement : dl.acm.org/citation.cfm?id=1064988 .

0 votes

Scott, j'ai lu ici blog.mikemccandless.com/2012/07/ qu'Azul fournit un module noyau qui pré-alloue de la mémoire pour l'utilisation de la JVM. Est-ce faux ? Si c'est vrai, ce n'est pas vraiment une modification du noyau, mais c'est quand même une modification.

13voto

emkays Points 126

Nous utilisons déjà G1GC, depuis presque deux ans. Il a fait ses preuves dans notre système de traitement des transactions critiques, et il s'est avéré être un excellent support en termes de débit élevé, de pauses réduites, de concurrence et de gestion optimisée de la mémoire.

Nous utilisons les paramètres JVM suivants :

-server -Xms512m -Xmx3076m -XX:NewRatio=50 -XX:+HeapDumpOnOutOfMemoryError -XX:+UseG1GC -XX:+UnlockExperimentalVMOptions -XX:+AggressiveOpts -XX:+DoEscapeAnalysis -XX:+UseCompressedOops -XX:MaxGCPauseMillis=400 -XX:GCPauseIntervalMillis=8000 -XX:+PrintGCTimeStamps -XX:+PrintGCApplicationStoppedTime -XX:+PrintGCApplicationConcurrentTime

5 votes

Avec Java 8, vous n'avez pas besoin de définir -XX:+UseCompressedOops ou -XX:+DoEscapeAnalysis, les stands sont activés par défaut. Voir : docs.oracle.com/javase/8/docs/technotes/tools/unix/java.html

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X