Published by

Il y a 7 mois -

Temps de lecture 6 minutes

Java est sur le point de devenir pauseless (Z Garbage Collector)

Introduction

Depuis Java 11, il y avait une fonctionnalité expérimentale qui est récemment devenue prête pour la production dans la 15e version de Java. Cette fonctionnalité mérite plus d’attention aujourd’hui, on souhaite donc la souligner.

La version contient un garbage collector ultra-rapide, ZGC, qui est développé par Oracle et qui promet des temps de pause très courts sur des heaps de plusieurs téraoctets. Cet article couvrira la motivation pour un nouveau GC, un aperçu technique et quelques-unes des techniques vraiment intéressantes que ZGC utilise pour atteindre ses résultats.

Motivation

Alors pourquoi le besoin d’un nouveau GC ? Pour mettre cela en perspective, G1, le GC le plus récent de Hotspot, a été introduit en 2006. À cette époque, la plus grande RAM d’instance AWS était de 1,7 Go, aujourd’hui AWS se fera un plaisir de vous louer une instance d’une taille de RAM d’environ 4 To. La conception de ZGC vise un avenir où ces types de capacités sont courants : des heaps de plusieurs téraoctets avec des temps de pause faibles (<10 ms) et un impact sur les performances globales des applications (<15% sur le throughput). Cela fait de ZGC un bon choix pour les applications qui nécessitent de grandes quantités de mémoire, comme avec le Big Data. Cependant, ZGC est également un bon candidat pour les petits heaps qui nécessitent des temps de pause prévisibles et extrêmement faibles.

Voyons le temps de pause du GC par rapport aux garbage collectors G1 et Parallel.

Figure 1. Les temps de pause du ZGC par rapport aux autres GC. Source : Conférence Jfokus [1]

On voit que ZGC est le leader en termes de temps de pause. Voyons comment ce leadership est atteint.

Figure 2. GCs précédents

On peut voir sur la figure 2 que l’une des techniques qui permet ce leadership est qu’il n’y a plus de division entre la young et la old générations. Et le fait que la majeure partie du travail soit effectuée en mode concurrent.

Juste avant de commencer, examinons quelques autres techniques que ZGC utilise pour obtenir de tels résultats.

Coloured Pointers

Figure 3. Pointeur d’objet 64 bits

La coloration du pointeur est une technique qui stocke les informations dans des pointeurs eux-mêmes. Cela est possible car sur les plates-formes 64 bits, un pointeur peut adresser beaucoup plus de mémoire qu’un système ne peut en avoir de manière réaliste et il est donc possible d’utiliser certains des autres bits pour stocker l’état. Par exemple, on peut stocker les informations indiquant que l’objet a été marqué ou déplacé.

Load Barrier

C’est un petit morceau de code injecté par le JIT à des endroits stratégiques. Dans le cas de ZGC, c’est lors du chargement d’une référence d’objet à partir du heap. Si l’objet chargé a une mauvaise couleur, une action sera entreprise. Ici, on peut voir un exemple de code.

String coffeeType = coffee.type; // Load an object reference from heap
< load barrier neede here>
String tmp = coffeeType;         // No barrier, not a load from heap 

En fait, la load barrier ressemble à ceci.

String coffeeType = coffee.type;
// Actually load barrier looks like this
if (coffeeType & bad_bit_mask) {  // if the reference has a bad colour  
  slow_path(register_for(coffeeType), address_of(coffee.type)); // jump in slow path to correct the colour of the reference
}

Il est nécessaire de corriger la couleur d’une référence avec une mauvaise couleur. Dans ZGC, il effectue cette tâche en testant la référence chargée pour voir si certains bits sont définis, en fonction de la phase actuelle. Si la référence réussit le test, aucun travail supplémentaire n’est effectué, si elle échoue, une tâche spécifique à la phase est effectuée avant que la référence ne soit renvoyée à l’application.

Phases ZGC

Sur l’image ci-dessous, vous pouvez voir l’aperçu du cycle GC.

Figure 4. Cycle GC

1 Pause Mark/Start

Analyser les piles de threads pour trouver des racines, un exemple de racines de GC sont des variables locales. Ils sont nécessaires pour construire un live set, des objets qui sont utilisés par l’application et qui ne seront pas supprimés.

2 Concurrent Mark/Remap

Parcourir le graphe d’objets à partir des racines GC pour trouver des objets vivants. Si un objet est accessible par une promenade du graphe d’objets à partir des racines, alors une application peut y accéder et il est considéré comme vivant. Tous les autres objets seront considérés comme des déchets et seront finalement supprimés.

3 Pause Mark End

Point de synchronisation pour terminer la phase de marquage.

4 Concurrent Prepare for Relocation

Inclut le traitement des reference processing, class unloading et relocation set selection

  • Reference processing signifie qu’il s’occupe des références douces, faibles et fantômes et de la finalisation.
  • Class unloading signifie que s’il y a un chargeur de classe et que certaines de ses ressources ne sont pas utilisées, elles seront libérées.
  • Relocation set selection signifie utiliser les informations de la phase de marquage afin que l’on puisse décider quelles parties du heap on peut compacter.

5 Relocate Start Pause

Scannez les piles de threads, trouvez les racines pointant vers les objets qui sont sur le point d’être déplacés, elles sont appelées relocation set.

6 Concurrent Relocate

Lourd travail de compactage du heap.

Les 3 pauses mentionnées ci-dessus prennent moins de 10 ms.

Conclusion

De nos jours, les serveurs peuvent avoir plusieurs téraoctets de RAM, ce qui fait clairement de ce garbage collector une fonctionnalité importante dans de tels cas. ZGC est conçu pour un temps de pause très court, il utilise des pointeurs de couleur et des barrières de charge pour atteindre ses objectifs.

ZGC effectue tous les travaux coûteux simultanément, sans arrêter l’exécution des threads d’application pendant plus de 10 ms, ce qui le rend adapté aux applications nécessitant une faible latence et / ou utilisant un très grand heap. Selon la documentation Oracle, il peut gérer des heaps de plusieurs téraoctets. Oracle a introduit ZGC dans Java 11. Le garbage collector Z exécute ses cycles dans ses threads. Il met l’application en pause pendant 1 ms en moyenne. Les collecteurs G1 et Parallel en moyenne environ 200 ms.

Pour activer Z Garbage Collector, on peut utiliser l’argument suivant :

java -XX:+UseZGC -jar Application.java

Références

  • Vous pouvez voir le journal des modifications ZGC pour chaque nouvelle version de Java ici.
  • source1
    Conférence Jfokus par Stefan Karlsson et Per Liden.

Published by

Commentaire

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Nous recrutons

Être un Sapient, c'est faire partie d'un groupe de passionnés ; C'est l'opportunité de travailler et de partager avec des pairs parmi les plus talentueux.