J'ai quelques questions à propos de l'algorithme GC: Tout d'abord, lorsque nous utilisons des paramètres tels que UseSerialGC, UseParallelGC, UseParallelOldGC, etc., nous spécifions un algorithme GC. Chacun d'entre eux peut faire du GC de toute génération, n'est-ce pas?
Par exemple, si j'utilise "Java -XX: + UseSerialGC", toute la génération utilisera la série GC comme algorithme GC.
Ensuite, puis-je utiliser ParallelGC dans Old Gneneration et utiliser SerialGC dans yong generation?
Le dernier en titre, quelle est la différence entre ParallelGC et ParallelOldGC?
Jetez un coup d’œil au HotSpot VM Options :
-XX: + UseParallelGC = Utiliser la récupération de place parallèle pour les nettoyages. (Introduit dans 1.4.1).
-XX: + UseParallelOldGC = Utiliser la récupération de place parallèle pour les collections complètes. L'activation de cette option définit automatiquement -XX: + UseParallelGC. (Introduit dans la version 5.0 mise à jour 6.)
où Scavenges = GC de la jeune génération.
Eh bien, après beaucoup de recherches et de recherches, ce que j’ai compris, c’est comme ci-dessous,
-XX: + UseParallelGC - Ceci permet au GC d'utiliser plusieurs threads dans nouvelle génération, mais pour la génération ancienne/permanente, toujours série et compact. _ l'algorithme est utilisé.
-XX: + UseParallelOldGC - Ceci permet au CPG d'utiliser l'algorithme marque parallèle et compact dans la génération ancienne/permanente.
Comprenons
L'algorithme et la disposition de la mémoire, tels que les marquages et les copies, les espaces d'échange, qui fonctionnent dans jeune génération ne fonctionnent pas pour ancienne génération pour de nombreuses raisons.
Faible mortalité - Dans la vieille génération, le "taux de mortalité" est sensiblement inférieur à celui de la jeune génération. Dans une application Java typique, la plupart des objets meurent rapidement et rares sont ceux qui vivent plus longtemps. En tant qu’objets qui survivent dans la jeune génération et sont promus dans l’ancienne génération, il est observé que ces objets ont tendance à vivre plus longtemps. Ce qui conduit à un taux de mortalité très inférieur chez les générations plus âgées par rapport aux générations plus jeunes.
Taille significative - La vieille génération est beaucoup plus grande que la jeune génération. Comme la jeune génération s'éclaircit rapidement, il y a relativement peu d'espace disponible pour les nombreux objets éphémères (petite jeune génération). Dans l'ancienne génération, les objets s'accumulent avec le temps. Par conséquent, il doit y avoir beaucoup plus d'espace dans une ancienne génération que dans la jeune génération (grande et vieille génération)
Petite allocation - Dans l'ancienne génération, il y a moins d'allocation que dans la jeune génération. En effet, dans la vieille génération, les objets n'apparaissent que lorsque le ramasse-miettes promeut les objets survivants, de la jeune génération à la vieille génération. Dans la jeune génération, en revanche, tous les objets générés par l’application avec de nouvelles ressources, c’est-à-dire la majorité des allocations, se produisent dans la jeune génération.
_ {En tenant compte de ces différences}, un algorithme a été choisi pour la jeune génération qui achèvera le ramassage des ordures le plus tôt possible car il doit être appelé souvent en raison du taux de mortalité élevé [point (1)]. . En outre, l'algorithme doit garantir que l'allocation de mémoire la plus efficace possible [point (3)] est alors possible, car une grande partie est allouée dans la jeune génération. L'algorithme de marquage et de copie de la jeune génération a ces propriétés.
D'autre part, cet algorithme n'a pas de sens sur l'ancienne génération. La situation est différente: le ramasse-miettes doit s'occuper de nombreux objets de l'ancienne génération [point (2)] et la plupart d'entre eux sont encore en vie; seule une petite partie est devenue inaccessible et peut être libérée [point (1)]. Si le ramasse-miettes copiait tous les objets survivants de chaque ramasse-miettes, comme il le fait avec les marques et copies, il passerait beaucoup de temps à les copier sans gagner beaucoup.
Par conséquent, l'algorithme balisage est créé sur l'ancienne génération, où rien n'est copié, mais simplement les objets inaccessibles sont libérés. Comme cet algorithme conduit à la fragmentation du tas, on a également considéré une variante de l’algorithme balise, dans lequel, après la phase de balayage, un compactage est effectué, par lequel le fragmentation est réduit. Cet algorithme s'appelle un algorithme mark-and-compact.
Un algorithme mark and compact peut prendre beaucoup de temps car il doit traverser le graphe d'objet en suivant les étapes.
Dans la phase Calcul du nouvel emplacement}, chaque fois qu'il obtient un espace libre, essaie de trouver un objet pouvant se déplacer dans cet espace (défragmentation). Stocke la paire pour une utilisation dans les phases ultérieures. Cela provoque l'algorithme consomme plus de temps.
Bien que marquer et comparer permettent de résoudre certains problèmes propres à la génération permanente, le problème est grave car il s’agit d’un événement STW (Stop the world) qui prend beaucoup de temps et qui peut avoir un impact important sur l’application.
Algorithmes alternatifs pour l'ancienne génération
Afin de réduire les temps de pause, des alternatives à l’algorithme série-compact ont été envisagées:
Un algorithme parallèle qui verrouille toujours tous les threads de l'application, mais gère ensuite l'étiquetage et le compactage ultérieur avec plusieurs threads du récupérateur de place. Bien qu'il s'agisse encore d'une approche globale, la pause qui en résulte est plus courte sur un ordinateur multi-cœur ou multi-processeur que l'algorithme série-compact. Cet algorithme parallèle sur l'ancienne génération (appelé "ParallelOld") est disponible depuis Java 5 Update 6 et est sélectionné avec l'option -XX: + UseParallelOldGC.
Algorithme _ {concurrent} _ qui rivalise au moins partiellement avec l'application sans arrêter ses threads et nécessite parfois de courtes phases d'arrêt du monde. Cet algorithme simultané de marquage (appelé "CMS") existe depuis Java 1.4.1; il est activé avec l'option -XX: + UseConcMarkSweepGC. Il est important de noter qu'il s'agit simplement d'un algorithme de balisage. La compaction n’a pas lieu, ce qui pose le problème déjà discuté de la fragmentation.
Donc, en résumé, -XX: + UseParallelOldGC est utilisé comme une indication pour utiliser plusieurs threads lors de la collecte de données majeure en utilisant l'algorithme Mark and Compact. Si cette option est utilisée à la place, les collections mineures ou nouvelles sont parallèles, mais les collections principales sont encore à thread unique.
J'espère que cela répond.
Ce sont deux stratégies gc appliquées à différentes régions d’un segment de mémoire Java, à savoir les générations nouvelle et ancienne. Voici un lien qui aide à préciser quelles options impliquent d’autres. C'est particulièrement utile lorsque vous commencez à comprendre ce que vous obtenez lorsque vous spécifiez, par exemple, ParallelOldGC ou ParNewGC. http://www.fasterj.com/articles/oraclecollectors1.shtml
À partir de la documentation Oracle Java SE 8:
https://docs.Oracle.com/javase/8/docs/technotes/guides/vm/gctuning/collectors.html
Le collecteur parallèle (également appelé collecteur de débit) effectue des collectes mineures en parallèle, ce qui peut réduire considérablement le temps système de la récupération de place. Il est destiné aux applications avec des ensembles de données de taille moyenne à grande, exécutées sur un matériel multiprocesseur ou multithread. Le collecteur parallèle est sélectionné par défaut sur certaines configurations de matériel et de système d'exploitation, ou peut être explicitement activé avec l'option -XX: + UseParallelGC.
Le compactage en parallèle est une fonctionnalité qui permet au collecteur parallèle d'effectuer des collections majeures en parallèle. Sans compactage parallèle, les collections principales sont effectuées à l'aide d'un seul thread, ce qui peut limiter considérablement l'évolutivité. Le compactage parallèle est activé par défaut si l'option -XX: + UseParallelGC a été spécifiée. L'option pour le désactiver est -XX: -UseParallelOldGC.
Donc, si vous spécifiez -XX: + UseParallelGC, par défaut, la collecte principale sera également effectuée à l'aide de plusieurs threads. L'inverse est également vrai si vous spécifiez -XX: + UseParallelOldGC, les collectes mineures seront également effectuées à l'aide de plusieurs threads.