[JAVA] Examinez les limites du "mur de mémoire de 32 Go" dans Elasticsearch

introduction

Elasticsearch a longtemps parlé de l'existence d'un "mur de 32 Go" dans la définition de la taille de la mémoire du tas JVM. Le paramètre par défaut est 1g pour Xms et Xmx, mais ce paramètre doit être dimensionné de manière appropriée en fonction de la quantité de mémoire installée dans le nœud.

À l'ère Elasticsearch 2.x, définissez la taille du tas JVM dans le Elasticsearch Definitive Guide. Il a été mentionné comme un conseil de performance qu'il ne dépasse pas 32 Go. Le [document officiel] actuel (https://www.elastic.co/guide/en/elasticsearch/reference/current/heap-size.html) recommande également que cette taille ne dépasse pas «environ» 32 Go. Ça a été.

Cet article résume comment trouver cette taille de mémoire seuil exacte dans un environnement. Notez que ce contenu varie en fonction de la version du système d'exploitation et de la version JDK, assurez-vous donc de bien suivre les étapes suivantes pour vérifier la taille exacte dans votre environnement.

Qu'est-ce qu'un «mur de 32 Go» (en gros)

Tout d'abord, il ne s'agit pas seulement d'Elasticsearch. C'est une histoire qui s'applique à toutes les applications JVM. En gros, le "mur de 32 Go" évoqué ici est lié à la fonction qui économise les ressources système en compressant la méthode de représentation du pointeur de référence de l'objet stocké dans le tas Java sur un système 64 bits. Il y a.

Il y a une explication détaillée sur le site suivant (* 1), mais normalement l'adresse du tas Java sur un système 64 bits est de 64 bits, mais seulement si la taille du tas est de 32 Go ou moins, c'est comme suit. C'est une astuce pour économiser de l'argent avec une adresse 32 bits en la maintenant dans les contraintes.

--Limitez l'adresse des objets du tas à une taille qui est un multiple de 8 (appelé alignement des objets)

En faisant cela, il est possible d'exprimer une adresse de 35 bits (= 2 ^ 35 ≒ 32 Go), qui n'était auparavant possible d'exprimer que 4 Go (= 2 ^ 32) avec 32 bits. Ce mécanisme est appelé "POO compressés" (voir Objets compressés).

*1: https://www.baeldung.com/jvm-compressed-oops

hoge

Bien sûr, cette méthode ne peut pas être utilisée avec une mémoire de tas de 32 Go ou plus, ce sera donc une référence d'objet normale utilisant 64 bits. Dans ce cas, l'efficacité d'utilisation de la mémoire est inférieure à celle de l'utilisation de la POO compressée, il est donc recommandé de ne pas définir la taille du tas au-delà de 32 Go de mémoire.

Procédure de vérification

Ici, nous utiliserons l'environnement suivant pour explorer la «limite» des POO compressés tout en modifiant la taille du tas. En conclusion, cette ligne de démarcation change en fonction du type de GC, nous étudions donc chacun des deux types de CMS: ConcMarkSweep) et G1GC qui peuvent être utilisés avec JDK11.

environnement

J'ai déployé une machine virtuelle / un système d'exploitation avec les spécifications suivantes sur Azure et installé OpenJDK et ELasticsearch.

Combinaison du type de GC et de la taille du tas

Nous avons vérifié avec les quatre combinaisons suivantes. Notez que la taille du tas de bordure est légèrement différente entre 01,02 et 03,04. (30 Mo différents) De plus, si la taille dépasse la taille de la ligne de délimitation pour chaque GC, comme 01 et 02, 03 et 04, les POO compressés ne peuvent pas être utilisés. Voici un résumé des étapes à suivre pour le vérifier.

no. Type de GC Taille du tas(Xms/Xmx) Peut-on utiliser Compressed Oops?
01 CMS(ConcMarkSweep) 32766MB Peut être utilisé
02 CMS(ConcMarkSweep) 32767MB Indisponible
03 G1GC 32736MB Peut être utilisé
04 G1GC 32737MB Indisponible

Procédure de confirmation (1) Confirmation avec la JVM seule

Tout d'abord, vérifiez la JVM seule. Cela utilise une méthode pour vérifier si la JVM fonctionne avec Compressed Oops en exécutant la commande java avec l'option "-XX: + PrintFlagsFinal".

01: CMS GC sous la frontière (32766 Mo)

Notez la dernière ligne de la sortie ci-dessous. La partie où "bool Use Compressed Oops = true" est la sortie lorsque Compressed Oops est activé. En d'autres termes, le «mur de 32 Go» n'est pas dépassé.

sodo@vm01:~$ java -XX:+UseConcMarkSweepGC -XX:+PrintFlagsFinal -Xms32766m -Xmx32766m 2>/dev/null | grep Compressed
   size_t CompressedClassSpaceSize                 = 1073741824                                {product} {default}
     bool UseCompressedClassPointers               = true                                 {lp64_product} {ergonomic}
     bool UseCompressedOops                        = true                                 {lp64_product} {ergonomic}

02: Border over (32767 Mo) avec CMS GC

"Bool Use CompressedOops = false", qui dépasse le "mur de 32 Go".

sodo@vm01:~$ java -XX:+UseConcMarkSweepGC -XX:+PrintFlagsFinal -Xms32767m -Xmx32767m 2>/dev/null | grep Compressed
   size_t CompressedClassSpaceSize                 = 1073741824                                {product} {default}
     bool UseCompressedClassPointers               = false                                {lp64_product} {default}
     bool UseCompressedOops                        = false                                {lp64_product} {default}

03: Sous la frontière à G1GC (32736 Mo)

Il dit "bool Use CompressedOops = true". Il ne dépasse pas le "mur de 32 Go".

sodo@vm01:~$ java -XX:+UseG1GC -XX:+PrintFlagsFinal -Xms32736m -Xmx32736m 2>/dev/null | grep Compressed
   size_t CompressedClassSpaceSize                 = 1073741824                                {product} {default}
     bool UseCompressedClassPointers               = true                                 {lp64_product} {ergonomic}
     bool UseCompressedOops                        = true                                 {lp64_product} {ergonomic}

04: Border over (32737 Mo) à G1GC

Il dit "bool Use CompressedOops = false". Il dépasse le "mur de 32 Go".

sodo@vm01:~$ java -XX:+UseG1GC -XX:+PrintFlagsFinal -Xms32737m -Xmx32737m 2>/dev/null | grep Compressed
   size_t CompressedClassSpaceSize                 = 1073741824                                {product} {default}
     bool UseCompressedClassPointers               = false                                {lp64_product} {default}
     bool UseCompressedOops                        = false                                {lp64_product} {default}

Procédure de confirmation ② Confirmation avec Elasticsearch

Ensuite, utilisez la recherche élastique pour spécifier la taille du tas dans le fichier jvm.option et vérifiez. Le résultat sera enregistré dans elasticsearch.log pour voir s'il est en mode Compressed Oops au démarrage, alors vérifiez cela.

01: CMS GC sous la frontière (32766 Mo)

Définissez les paramètres suivants dans le fichier jvm.option. Les lignes 3 à 7 sont laissées à leurs valeurs par défaut. Puisque nous utilisons OpenJDK11 cette fois, CMS est utilisé pour GC. (Le type GC utilisé pour gc.log est également affiché)

jvm.options


-Xms32766m
-Xmx32766m

# 10-13:-XX:-UseConcMarkSweepGC
# 10-13:-XX:-UseCMSInitiatingOccupancyOnly
14-:-XX:+UseG1GC
14-:-XX:G1ReservePercent=25
14-:-XX:InitiatingHeapOccupancyPercent=30

Lorsque vous démarrez Elasticsearch avec ce paramètre, vous verrez la ligne suivante dans le journal: "Pointeurs d'objets ordinaires compressés [vrai]" à la fin de la ligne est un signe que Compressed Oops est valide.

elasticsearch.log


[2020-03-30T07:26:14,269][INFO ][o.e.e.NodeEnvironment    ] [vm01] heap size [31.9gb], compressed ordinary object pointers [true]

02: Border over (32767 Mo) avec CMS GC

Définissez les paramètres suivants dans le fichier jvm.option. Seule la taille du tas des 1ère et 2ème lignes est modifiée.

jvm.options


-Xms32767m
-Xmx32767m

# 10-13:-XX:-UseConcMarkSweepGC
# 10-13:-XX:-UseCMSInitiatingOccupancyOnly
14-:-XX:+UseG1GC
14-:-XX:G1ReservePercent=25
14-:-XX:InitiatingHeapOccupancyPercent=30

Cette fois, il est devenu "des pointeurs d'objets ordinaires compressés [faux]". Vous pouvez voir que Compressed Oops a été désactivé.

elasticsearch.log


[2020-03-30T09:43:01,828][INFO ][o.e.e.NodeEnvironment    ] [vm01] heap size [31.9gb], compressed ordinary object pointers [false]

03: Sous la frontière à G1GC (32736 Mo)

Les paramètres du CPG sont modifiés en fonction des commentaires dans le fichier de paramètres ainsi que de la taille du tas. Puisque nous utilisons OpenJDK11 cette fois, G1GC est utilisé avec ce paramètre. (J'ai également vérifié la sortie de gc.log)

jvm.options


-Xms32736m
-Xmx32736m

10-13:-XX:-UseConcMarkSweepGC
10-13:-XX:-UseCMSInitiatingOccupancyOnly
11-:-XX:+UseG1GC
11-:-XX:G1ReservePercent=25
11-:-XX:InitiatingHeapOccupancyPercent=30

Compressed Oops est activé ici.

elasticsearch.log


[2020-03-30T07:22:29,694][INFO ][o.e.e.NodeEnvironment    ] [vm01] heap size [31.9gb], compressed ordinary object pointers [true]

04: Border over (32737 Mo) à G1GC

Augmentez la taille du tas de 1 Mo. D'autres n'ont pas changé.

jvm.options


-Xms32737m
-Xmx32737m

10-13:-XX:-UseConcMarkSweepGC
10-13:-XX:-UseCMSInitiatingOccupancyOnly
11-:-XX:+UseG1GC
11-:-XX:G1ReservePercent=25
11-:-XX:InitiatingHeapOccupancyPercent=30

Cette fois, Compressed Oops est désactivé.

elasticsearch.log


[2020-03-30T07:23:19,486][INFO ][o.e.e.NodeEnvironment    ] [vm01] heap size [31.9gb], compressed ordinary object pointers [false]

Résumé

Concernant le «mur de 32 Go» souvent mentionné dans Elasticsearch, un aperçu du mécanisme de Compressed Oops (voir objets compressés) lié à JVM en général, et la procédure pour vérifier si Compressed Oops est activé ou désactivé lors du démarrage de JVM et Elasticsearch dans l'environnement réel. Je l'ai présenté. En fait, lorsque l'on considère une taille de tas appropriée, il y a quelques points à considérer, tels que l'objectif d'Elasticsearch (centre de recherche en texte intégral, centre de tri métrique / d'agrégation, etc.) et la mémoire cache utilisée par Lucene. Si vous avez des questions, il est recommandé de demander à un site communautaire tel que discuss.elastic.co, ou de demander à un expert lors d'une communauté d'utilisateurs / session d'étude telle que Elasticsearch Tokyo User Group.

Recommended Posts

Examinez les limites du "mur de mémoire de 32 Go" dans Elasticsearch
Examiner l'utilisation de la mémoire des éléments Java
L'histoire de @ViewScoped dévore la mémoire
Examinez la liste des ID de fuseau horaire disponibles dans la classe Java ZoneId
Ordre de traitement dans le programme
Obtenez le résultat de POST en Java
L'identité des paramètres de rails [: id]
L'histoire de l'écriture de Java dans Emacs
Ecrire le mouvement de Rakefile dans le runbook
[Order method] Définit l'ordre des données dans Rails
L'histoire de la comparaison de chaînes de bas niveau en Java
[Java] Gestion des Java Beans dans la chaîne de méthodes
L'histoire de la fabrication d'un Othello ordinaire à Java
À propos de l'idée des classes anonymes en Java
L'histoire de l'apprentissage de Java dans la première programmation
Mesurer la taille d'un dossier avec Java
Ressentez le passage du temps même à Java
Importer des fichiers de la même hiérarchie en Java