L'utilisation plus que la taille

L'utilisation plus que la taille




🛑 TOUTES LES INFORMATIONS CLIQUEZ ICI đŸ‘ˆđŸ»đŸ‘ˆđŸ»đŸ‘ˆđŸ»

































L'utilisation plus que la taille




java 

linux 

docker 

memory 

jvm 







—

Nicolas Henneaux



source





Le tas est l'endroit oĂč les objets sont allouĂ©s, mais la JVM a de nombreuses autres rĂ©gions de mĂ©moire, notamment des bibliothĂšques partagĂ©es, des tampons de mĂ©moire directs, des piles de threads, des composants d'interface graphique, une mĂ©ta-espace. Vous devez examiner la taille de la JVM et rendre la limite suffisamment Ă©levĂ©e pour que vous prĂ©fĂ©riez que le processus meure plutĂŽt que d'en utiliser davantage.


Il semble que le GC utilise beaucoup de mémoire. Vous pouvez essayer d'utiliser le collecteur CMS à la place. Il semble qu'environ 125 Mo sont utilisés pour le code metaspace +, mais sans réduire votre base de code, il est peu probable que vous puissiez la réduire. L'espace engagé est proche de votre limite, il n'est donc pas surprenant qu'il soit tué.


oĂč / comment dĂ©finissez-vous la configuration -Xms et -Xmx?


Le programme exĂ©cute-t-il de nombreuses opĂ©rations sur les fichiers (par exemple, crĂ©e des fichiers en gigaoctet)? Si tel est le cas, sachez que cela cgroups ajoute un cache disque Ă  la mĂ©moire utilisĂ©e - mĂȘme s'il est gĂ©rĂ© par le noyau et qu'il est invisible pour le programme utilisateur. (Attention, commandes ps et docker stats ne comptez pas le cache disque.)




—
apangin


source





Les chaĂźnes internes ne sont-elles pas dans le tas depuis jdk7? ( bugs.java.com/bugdatabase/view_bug.do?bug_id=6962931 ) - peut-ĂȘtre que je me trompe.


@ j-keck Les objets String sont dans le tas, mais la table de hachage (les buckets et les entrĂ©es avec rĂ©fĂ©rences et codes de hachage) est en mĂ©moire hors tas. J'ai reformulĂ© la phrase pour ĂȘtre plus prĂ©cise. Merci de l'avoir signalĂ©.


Pour ajouter Ă  cela, mĂȘme si vous utilisez des ByteBuffers non directs, la JVM allouera des tampons directs temporaires dans la mĂ©moire native sans aucune limite de mĂ©moire imposĂ©e. Cf. evanjones.ca/java-bytebuffer-leak.html




—
Jan Garaj


source





C'est en effet mieux avec -XX:MaxRam . Je pense qu'il utilise encore plus que le maximum défini mais c'est mieux, merci!


Peut-ĂȘtre avez-vous vraiment besoin de plus de mĂ©moire pour cette instance Java. Il y a 15267 classes, 56 threads.


Voici plus de dĂ©tails, les arguments Java -Xmx128m -Xms128m -Xss228k -XX:MaxRAM=256m -XX:+UseSerialGC , produit Docker 428.5MiB / 600MiB et jcmd 58 VM.native_memory -> Native Memory Tracking: Total: reserved=1571296KB, committed=314316KB . JVM prend environ 300 Mo tandis que le conteneur a besoin de 430 Mo. OĂč sont les 130 Mo entre les rapports JVM et les rapports OS?


Ajout d'informations / lien sur la mémoire RSS.


Le RSS fourni provient de l'intérieur du conteneur pour le processus Java uniquement ps -p 71 -o pcpu,rss,size,vsize avec le processus Java ayant pid 71. En -XX:MaxRam fait, cela n'aidait pas, mais le lien que vous avez fourni aide avec le GC série.




—
Nicolas Henneaux


source







—
adiien


source





L'utilisation jlink est assez contraignante car elle nécessitait une modularisation de l'application. Le module automatique n'est pas pris en charge, il n'y a donc pas de moyen facile d'y aller.




—
v_sukt


source








En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité .





Licensed under cc by-sa 3.0
with attribution required.



Pour mon application, la mémoire utilisée par le processus Java est bien supérieure à la taille du tas.
Le systÚme sur lequel les conteneurs sont exécutés commence à avoir des problÚmes de mémoire car le conteneur utilise beaucoup plus de mémoire que la taille du tas.
La taille du tas est définie sur 128 Mo ( -Xmx128m -Xms128m ) tandis que le conteneur occupe jusqu'à 1 Go de mémoire. Dans des conditions normales, il a besoin de 500 Mo. Si le conteneur docker a une limite inférieure (par exemple mem_limit=mem_limit=400MB ), le processus est tué par le tueur de mémoire insuffisante du systÚme d'exploitation.
Pouvez-vous expliquer pourquoi le processus Java utilise beaucoup plus de mémoire que le tas? Comment dimensionner correctement la limite de mémoire Docker? Existe-t-il un moyen de réduire l'empreinte mémoire hors tas du processus Java?
Je rassemble quelques détails sur le problÚme à l'aide de la commande du suivi de la mémoire native dans JVM .
Du systÚme hÎte, j'obtiens la mémoire utilisée par le conteneur.
De l'intérieur du conteneur, j'obtiens la mémoire utilisée par le processus.
L'application est un serveur Web utilisant Jetty / Jersey / CDI dans un gros lointain de 36 Mo.
La version suivante du systÚme d'exploitation et de Java est utilisée (à l'intérieur du conteneur). L'image Docker est basée sur openjdk:11-jre-slim .
La mémoire virtuelle utilisée par un processus Java va bien au-delà du simple Java Heap. Vous savez, JVM comprend de nombreux sous-systÚmes: Garbage Collector, Class Loading, JIT compilers etc., et tous ces sous-systÚmes nécessitent une certaine quantité de RAM pour fonctionner.
JVM n'est pas le seul consommateur de RAM. Les bibliothĂšques natives (y compris la bibliothĂšque de classes Java standard) peuvent Ă©galement allouer de la mĂ©moire native. Et cela ne sera mĂȘme pas visible pour le suivi de la mĂ©moire native. L'application Java elle-mĂȘme peut Ă©galement utiliser de la mĂ©moire hors tas au moyen de ByteBuffers directs.
Alors, qu'est-ce qui prend de la mémoire dans un processus Java?
La partie la plus évidente. C'est là que vivent les objets Java. Heap prend jusqu'à la -Xmx quantité de mémoire.
Les structures et algorithmes GC nécessitent une mémoire supplémentaire pour la gestion du tas. Ces structures sont Mark Bitmap, Mark Stack (pour parcourir le graphe d'objets), Remembered Sets (pour enregistrer des références inter-régions) et autres. Certains d'entre eux sont directement réglables, par exemple -XX:MarkStackSizeMax , d'autres dépendent de la disposition du tas, par exemple plus les régions G1 sont grandes ( -XX:G1HeapRegionSize ), plus les ensembles sont mémorisés plus petits.
La surcharge de mémoire GC varie selon les algorithmes GC. -XX:+UseSerialGC et -XX:+UseShenandoahGC ont les plus petits frais généraux. G1 ou CMS peuvent facilement utiliser environ 10% de la taille totale du tas.
Contient du code généré dynamiquement: méthodes compilées par JIT, interpréteur et stubs d'exécution. Sa taille est limitée par -XX:ReservedCodeCacheSize (240M par défaut). Désactivez -XX:-TieredCompilation pour réduire la quantité de code compilé et donc l'utilisation du cache de code.
Le compilateur JIT lui-mĂȘme a Ă©galement besoin de mĂ©moire pour faire son travail. Ceci peut ĂȘtre rĂ©duit Ă  nouveau en coupant Tiered Compilation ou en rĂ©duisant le nombre de fils de compilateur: -XX:CICompilerCount .
Les mĂ©tadonnĂ©es de classe (bytecodes de mĂ©thode, symboles, pools de constantes, annotations, etc.) sont stockĂ©es dans une zone hors tas appelĂ©e Metaspace. Plus il y a de classes chargĂ©es - plus la mĂ©taspace est utilisĂ©e. L'utilisation totale peut ĂȘtre limitĂ©e par -XX:MaxMetaspaceSize (illimitĂ© par dĂ©faut) et -XX:CompressedClassSpaceSize (1G par dĂ©faut).
Deux principales tables de hachage de la JVM: la table Symbol contient des noms, des signatures, des identifiants, etc. et la table String contient des références à des chaßnes internées. Si le suivi de la mémoire native indique une utilisation importante de la mémoire par une table String, cela signifie probablement que l'application appelle excessivement String.intern .
Les piles de threads sont également responsables de la prise de RAM. La taille de la pile est contrÎlée par -Xss . La valeur par défaut est de 1M par thread, mais heureusement, les choses ne sont pas si mauvaises. Le systÚme d'exploitation alloue les pages de mémoire paresseusement, c'est-à-dire lors de la premiÚre utilisation, de sorte que l'utilisation réelle de la mémoire sera beaucoup plus faible (généralement 80-200 Ko par pile de threads). J'ai écrit un script pour estimer la part de RSS appartenant aux piles de threads Java.
Il existe d'autres composants JVM qui allouent de la mémoire native, mais ils ne jouent généralement pas un rÎle important dans la consommation totale de mémoire.
Une application peut demander explicitement de la mĂ©moire hors tas en appelant ByteBuffer.allocateDirect . La limite par dĂ©faut hors tas est Ă©gale Ă  -Xmx , mais elle peut ĂȘtre remplacĂ©e par -XX:MaxDirectMemorySize . Les ByteBuffers directs sont inclus dans la Other section de sortie NMT (ou Internal avant JDK 11).
La quantité de mémoire directe utilisée est visible via JMX, par exemple dans JConsole ou Java Mission Control:
En plus des ByteBuffers directs, il peut y avoir MappedByteBuffers - les fichiers mappés à la mémoire virtuelle d'un processus. NMT ne les suit pas, cependant, MappedByteBuffers peut également prendre de la mémoire physique. Et il n'y a pas de moyen simple de limiter ce qu'ils peuvent prendre. Vous pouvez simplement voir l'utilisation réelle en regardant la carte mémoire du processus: pmap -x
Le code JNI chargé par System.loadLibrary peut allouer autant de mémoire hors tas qu'il le souhaite sans aucun contrÎle du cÎté JVM. Cela concerne également la bibliothÚque de classes Java standard. En particulier, les ressources Java non fermées peuvent devenir une source de fuite de mémoire native. Des exemples typiques sont ZipInputStream ou DirectoryStream .
Les agents JVMTI, en particulier l' jdwp agent de débogage, peuvent également entraßner une consommation excessive de mémoire.
Cette réponse décrit comment profiler les allocations de mémoire natives avec async-profiler .
Un processus demande gĂ©nĂ©ralement de la mĂ©moire native soit directement du systĂšme d'exploitation (par mmap appel systĂšme), soit en utilisant l' malloc allocateur libc standard. À son tour, malloc demande de gros morceaux de mĂ©moire Ă  partir du systĂšme d'exploitation mmap , puis gĂšre ces morceaux en fonction de son propre algorithme d'allocation. Le problĂšme est que cet algorithme peut entraĂźner une fragmentation et une utilisation excessive de la mĂ©moire virtuelle .
jemalloc , un allocateur alternatif, semble souvent plus intelligent que la libc ordinaire malloc , donc le passage Ă  jemalloc peut entraĂźner une plus petite empreinte gratuite.
Il n'existe aucun moyen garanti d'estimer l'utilisation totale de la mémoire d'un processus Java, car il y a trop de facteurs à prendre en compte.
Il est possible de réduire ou de limiter certaines zones de mémoire (comme le cache de code) par des indicateurs JVM, mais beaucoup d'autres ne sont pas du tout sous le contrÎle de la JVM.
Une approche possible pour définir les limites de Docker serait de surveiller l'utilisation réelle de la mémoire dans un état «normal» du processus. Il existe des outils et des techniques pour étudier les problÚmes de consommation de mémoire Java: Native Memory Tracking , pmap , jemalloc , async-profiler .
Voici un enregistrement de ma présentation Empreinte mémoire d'un processus Java .
Dans cette vidéo, je discute de ce qui peut consommer de la mémoire dans un processus Java, comment surveiller et limiter la taille de certaines zones de mémoire et comment profiler les fuites de mémoire native dans une application Java.
Pourquoi est-ce lorsque je spécifie -Xmx = 1g ma JVM utilise plus de mémoire que 1 Go de mémoire?
Spécifier -Xmx = 1g indique à la JVM d'allouer un tas de 1 Go. Il ne dit pas à la JVM de limiter toute son utilisation de la mémoire à 1 Go. Il existe des tables de cartes, des caches de code et toutes sortes d'autres structures de données hors tas. Le paramÚtre que vous utilisez pour spécifier l'utilisation totale de la mémoire est -XX: MaxRAM. Sachez qu'avec -XX: MaxRam = 500m, votre tas sera d'environ 250 Mo.
Java voit la taille de la mémoire de l'hÎte et ne connaßt aucune limitation de la mémoire du conteneur. Cela ne crée pas de pression sur la mémoire, donc GC n'a pas non plus besoin de libérer la mémoire utilisée. J'espÚre que XX:MaxRAM cela vous aidera à réduire l'empreinte mémoire. Finalement, vous pouvez modifier la configuration GC ( -XX:MinHeapFreeRatio , -XX:MaxHeapFreeRatio , ...)
Il existe de nombreux types de mĂ©triques de mĂ©moire. Docker semble signaler la taille de la mĂ©moire RSS, qui peut ĂȘtre diffĂ©rente de la mĂ©moire «engagĂ©e» rapportĂ©e par jcmd (les anciennes versions de Docker rapportent le cache RSS + comme utilisation de la mĂ©moire). Bonne discussion et liens: DiffĂ©rence entre Resident Set Size (RSS) et la mĂ©moire totale engagĂ©e Java (NMT) pour une JVM exĂ©cutĂ©e dans un conteneur Docker
La mĂ©moire (RSS) peut Ă©galement ĂȘtre consommĂ©e par d'autres utilitaires du conteneur - shell, gestionnaire de processus, ... Nous ne savons pas ce qui est en cours d'exĂ©cution dans le conteneur et comment dĂ©marrer les processus dans le conteneur.
L'utilisation détaillée de la mémoire est fournie par les détails NMT (Native Memory Tracking) (principalement les métadonnées du code et le garbage collector). En plus de cela, le compilateur et l'optimiseur Java C1 / C2 consomment la mémoire non signalée dans le résumé.
L'encombrement mĂ©moire peut ĂȘtre rĂ©duit Ă  l'aide des indicateurs JVM (mais il y a des impacts).
Le dimensionnement du conteneur Docker doit ĂȘtre effectuĂ© via des tests avec la charge attendue de l'application.
L' espace de classe partagĂ© peut ĂȘtre dĂ©sactivĂ© Ă  l'intĂ©rieur d'un conteneur car les classes ne seront pas partagĂ©es par un autre processus JVM. Le drapeau suivant peut ĂȘtre utilisĂ©. Cela supprimera l'espace de classe partagĂ© (17 Mo).
Le garbage collector sĂ©rie du a une empreinte mĂ©moire minimale au prix d'un temps de pause plus long pendant le traitement du ramasse-miettes (voir la comparaison d'Aleksey ShipilĂ«v entre GC sur une image ). Il peut ĂȘtre activĂ© avec l'indicateur suivant. Il peut Ă©conomiser jusqu'Ă  l'espace GC utilisĂ© (48 Mo).
le compilateur C2 peut ĂȘtre dĂ©sactivĂ© avec l'indicateur suivant pour rĂ©duire les donnĂ©es de profilage utilisĂ©es pour dĂ©cider d'optimiser ou non une mĂ©thode.
L'espace de code est réduit de 20 Mo. De plus, la mémoire hors JVM est réduite de 80 Mo (différence entre l'espace NMT et l'espace RSS). Le compilateur d'optimisation C2 a besoin de 100 Mo.
Les compilateurs C1 et C2 peuvent ĂȘtre dĂ©sactivĂ©s avec l'indicateur suivant.
La mémoire en dehors de la JVM est maintenant inférieure à l'espace total engagé. L'espace de code est réduit de 43 Mo. Attention, cela a un impact majeur sur les performances de l'application. La désactivation du compilateur C1 et C2 réduit la mémoire utilisée de 170 Mo.
L'utilisation du compilateur Graal VM (remplacement de C2) conduit à une empreinte mémoire un peu plus petite. Il augmente de 20 Mo l'espace mémoire du code et diminue de 60 Mo de la mémoire JVM extérieure.
Java a besoin de beaucoup de mĂ©moire. La JVM elle-mĂȘme a besoin de beaucoup de mĂ©moire pour fonctionner. Le tas est la mĂ©moire disponible Ă  l'intĂ©rieur de la machine virtuelle, disponible pour votre application. Parce que JVM est un gros paquet contenant tous les bonus possibles, il faut beaucoup de mĂ©moire juste pour le charger.
À partir de java 9, vous avez quelque chose appelĂ© project Jigsaw , qui peut rĂ©duire la mĂ©moire utilisĂ©e lorsque vous dĂ©marrez une application java (avec l'heure de dĂ©but). Le puzzle de projet et un nouveau systĂšme de modules n'ont pas nĂ©cessairement Ă©tĂ© crĂ©Ă©s pour rĂ©duire la mĂ©moire nĂ©cessaire, mais si c'est important, vous pouvez essayer.
Vous pouvez consulter cet exemple: https://steveperkins.com/using-java-9-modularization-to-ship-zero-dependency-native-apps/ . En utilisant le systÚme de modules, il en a résulté une application CLI de 21 Mo (avec JRE intégré). JRE prend plus de 200 Mo. Cela devrait se traduire par moins de mémoire allouée lorsque l'application est active (un grand nombre de classes JRE inutilisées ne seront plus chargées).
Si vous ne voulez pas passer du temps avec cela, vous pouvez simplement allouer plus de mémoire. Parfois c'est le meilleur.
Comment dimensionner correctement la limite de mémoire Docker?
Vérifiez l'application en la surveillant pendant un certain temps. Pour limiter la mémoire du conteneur, essayez d'utiliser l'option -m, --memory bytes pour la commande docker run - ou quelque chose d'équivalent si vous l'exécutez autrement comme
ne peut pas répondre à d'autres questions.



We use cookies and other tracking technologies to improve your browsing experience on our website,
to show you personalized content and targeted ads, to analyze our website traffic,
and to understand where our visitors are coming from.





By continuing, you consent to our use of cookies and other tracking technologies and
affirm you're at least 16 years old or have consent from a parent or guardian.





You can read details in our
Cookie policy and
Privacy policy .





Veille bibliographique en kinésithérapie


Vous disposez dĂ©jĂ  dÊŒun compte WordPress ? Connectez-vous maintenant.




kinotes.fr



Personnaliser




Suivre


Abonné


Une secrétaire sous la table
Des mannequins sodomisées
Fille latina sexy avec un beau corps

Report Page