Maison > Périphériques technologiques > Industrie informatique > Que fait la machine virtuelle Java toute la journée?

Que fait la machine virtuelle Java toute la journée?

尊渡假赌尊渡假赌尊渡假赌
Libérer: 2025-02-08 10:02:08
original
241 Les gens l'ont consulté

What Does the Java Virtual Machine Do All Day?

Cet article a été initialement publié par Ampere Computing

J'ai vu un article de blog récent sur GPROFNG, un nouvel outil d'analyse des performances GNU. Ce blog utilise un programme de multiplication vectoriel matriciel écrit dans le langage C comme exemple. Je suis un programmeur Java ™ et j'utilise des outils conçus pour la programmation C compilée statiquement compilée est souvent difficile à analyser les applications Java car les programmes Java sont compilés au moment de l'exécution. Dans cet article de blog, je montrerai que GPROFNG est facile à utiliser et est très utile pour plonger dans le comportement dynamique des applications Java.

La première étape consiste à écrire un programme de multiplication matriciel. J'ai écrit un programme complet de matrice de multiplication de matrice car il n'est pas plus difficile que les vecteurs de multiplication matricielle. Il existe trois méthodes principales: une méthode calcule la multiplication et l'opération d'addition la plus interne, une méthode combine le fonctionnement de multiplication et d'addition en un seul élément du résultat, et une méthode itère sur chaque élément du résultat.

J'enveloppe les calculs dans un programme de test simple pour calculer à plusieurs reprises le produit matriciel pour garantir que le temps est reproductible. (Voir note 1.) Le programme imprime le temps où chaque multiplication matricielle commence (par rapport au moment où la machine virtuelle Java est démarrée) et le temps nécessaire pour chaque multiplication matricielle. Ici, j'ai exécuté le programme de test pour multiplier deux matrices 8000 × 8000. Le programme de test a répété le calcul 11 ​​fois et pour mieux mettre en évidence le comportement ultérieur, dormir pendant 920 millisecondes entre les répétitions:

$ numactl --cpunodebind=0 --membind=0 -- \
java -XX:+UseParallelGC -Xms31g -Xmx31g -Xlog:gc -XX:-UsePerfData \
  MxV -m 8000 -n 8000 -r 11 -s 920
Copier après la connexion

What Does the Java Virtual Machine Do All Day?

Figure 1: Exécution du programme de multiplication de la matrice

Veuillez noter que la deuxième répétition prend 92% du temps de la première répétition, tandis que la dernière répétition ne prend que 89% du temps de la première répétition. Ces changements dans le temps d'exécution confirment que les programmes Java ont besoin de temps pour se réchauffer.

La question est: puis-je utiliser gprofng pour voir ce qui se passe entre les premier et les dernières répétitions, entraînant des améliorations des performances?

Une façon de répondre à cette question est d'exécuter le programme et de faire collecter des informations en cours d'exécution. Heureusement, c'est facile: j'ai juste besoin de préfixer la ligne de commande pour collecter ce que GProfng appelle des informations "expérimentales":

$ numactl --cpunodebind=0 --membind=0 -- \
gprofng collect app \
    java -XX:+UseParallelGC -Xms31g -Xmx31g -Xlog:gc --XX:-UsePerfData \
        MxV -m 8000 -n 8000 -r 11 -s 920
Copier après la connexion

What Does the Java Virtual Machine Do All Day?

Figure 2: Exécution du programme de multiplication de la matrice sous gprofng

La première chose à noter est que, comme tout outil d'analyse des performances, la collecte d'informations d'analyse des performances peut coûter l'application. Par rapport aux courses non analysées précédentes, le GPROFNG ne semble pas provoquer des frais généraux significatifs.

Je peux ensuite demander comment le temps est passé dans Gprofng toute l'application. (Voir note 2.) Pour toute la course, les 24 méthodes les plus populaires de GProfng sont:

$ gprofng display text test.1.er -viewmode expert -limit 24 -functions
Copier après la connexion

What Does the Java Virtual Machine Do All Day?

Figure 3: 24 façons de montrer le gprofng

le plus chaud

La vue de fonction ci-dessus donne le temps de processeur exclusif et d'inclusion pour chaque méthode, exprimée en pourcentage de secondes et temps total du processeur. La fonction nommée est une pseudo-fonction générée par gprofng, avec la valeur totale de divers indicateurs. Dans ce cas, je vois que le temps de processeur total de l'ensemble de l'application est de 1,201 secondes.

Les méthodes d'application (celles de la classe MXV) y sont toutes, occupant la majeure partie du temps du CPU, mais il existe d'autres méthodes, y compris le compilateur d'exécution JVM (compilation :: compilation), et d'autres fonctions qui ne font pas partie de Le programme de multiplication matricielle. Cet affichage de l'ensemble de l'exécution du programme capture les codes d'allocation (MXV.Allocate) et d'initialisation (MXV.Initialize), qui ne m'intéressent pas beaucoup car ils font partie du programme de test, ne sont utilisés que pendant le démarrage et sont multipliés Avec la matrice, cela n'a guère d'importance.

Je peux utiliser gprofng pour suivre les parties de l'application qui m'intéresse. Une grande caractéristique de GPROFNG est qu'après avoir collecté des expériences, je peux appliquer le filtre aux données collectées. Par exemple, regardez ce qui se passe au cours d'un intervalle de temps spécifique, ou ce qui se passe lorsqu'une méthode spécifique est sur la pile d'appels. À des fins de démonstration et pour faciliter le filtrage, j'ai ajouté un appel stratégique à Thread.Sleep (MS) pour faciliter l'écriture de filtres en fonction des phases du programme (divisé par un second intervalle). C'est pourquoi la sortie du programme de la figure 1 ci-dessus est d'environ une seconde entre chaque répétition, même si chaque multiplication matricielle ne prend que 0,1 seconde environ.

gprofng est scriptable, j'ai donc écrit un script pour extraire une seule seconde de l'expérience GProfng. La première seconde concerne le démarrage de la machine virtuelle Java.

What Does the Java Virtual Machine Do All Day?

Figure 4: La méthode la plus chaude pour filtrer la première seconde. Dans cette seconde, la multiplication de la matrice a été retardée manuellement afin que je puisse montrer le démarrage JVM

Je peux voir que le compilateur commence à l'exécution (par exemple, compilation :: compile_java_method, 16% du temps CPU), même si une méthode de l'application n'a pas encore commencé à s'exécuter. (L'appel de multiplication de la matrice a été retardé par l'appel de sommeil que j'ai inséré.)

La première seconde est une seconde, au cours de laquelle les méthodes d'allocation et d'initialisation s'exécutent avec diverses méthodes JVM, mais le code de multiplication matriciel n'a pas encore commencé.

What Does the Java Virtual Machine Do All Day?

Figure 5: La méthode la plus chaude de la deuxième seconde. L'allocation et l'initialisation de la matrice rivalisent avec le démarrage JVM

Maintenant que le démarrage JVM et l'allocation et l'initialisation du tableau ont été terminés, il y a la première répétition du code de multiplication de la matrice dans la troisième seconde, comme le montre la figure 6. Mais notez que le code de multiplication de la matrice est en concurrence avec le compilateur Java Runtime (par exemple CompileBroker :: invoke_compiler_on_method, 8% sur la figure 6) qui compile les méthodes car le code de multiplication matriciel est chaud.

Malgré cela, le code de multiplication de la matrice (par exemple, "inclut" le temps dans la méthode MXV.Main, 91%) obtient toujours la majeure partie du temps du CPU. Le temps d'inclusion indique que la multiplication de la matrice (par exemple, MXV.Multiply) prend 0,100 secondes de processeur, ce qui est cohérent avec le temps réel rapporté par l'application de la figure 2. (Il faut un peu de temps pour collecter et signaler le temps réel, qui est en dehors du temps du CPU gprofng compte pour mxv.Multiply.)

What Does the Java Virtual Machine Do All Day?

Figure 6: La méthode la plus chaude de la troisième seconde, indiquant que le compilateur d'exécution est en concurrence avec la méthode de multiplication matricielle

Dans cet exemple particulier, la multiplication matricielle ne rivalise pas vraiment pour le temps du CPU, car les tests s'exécutent sur un système multiprocesseur qui a un grand nombre de cycles d'inactivité et le compilateur d'exécution s'exécute en tant que thread séparé. Dans des cas plus restrictifs, comme sur les machines partagées avec des charges lourdes, 8% du temps passé par le compilateur d'exécution peut être un problème. D'un autre côté, le temps passé dans le compilateur d'exécution se traduit par une implémentation de méthode plus efficace, donc si je calcule de nombreuses multiplications matricielles, ce serait un investissement que je suis prêt à faire.

À la cinquième seconde, le code de multiplication de la matrice a la machine virtuelle Java.

What Does the Java Virtual Machine Do All Day?

Figure 7: Toutes les méthodes s'exécutent pendant la cinquième seconde, indiquant que seule la méthode de multiplication de la matrice est active

Veuillez noter l'allocation de 60% / 30% / 10% entre MXV.OneCell, MXV.MultiplyAdd et Mxv.Multiply en termes de secondes CPU exclusives. La méthode MXV.MultiplyAdd ne calcule que la multiplication et l'ajout: mais c'est la méthode la plus interne dans la multiplication matricielle. MXV.OneCell a une boucle pour appeler MXV.MultiplyAdd. Je peux voir que les frais généraux et les appels de boucle (conditions d'évaluation et le transfert de contrôle) fonctionnent relativement plus que les opérations arithmétiques directes dans MXV.Multiplyadd. (MXV.OneCell a un temps exclusif de 0,060 seconde CPU, tandis que MXV.MultiplyAdd est de 0,030 seconde de processeur, reflétant cette différence.) La fréquence d'exécution de la boucle externe ne l'a pas encore compilée. , mais la méthode utilise 0,010 seconde de CPU.

La multiplication matricielle se poursuit jusqu'à la neuvième seconde, lorsque le compilateur d'exécution JVM recommence et constate que Mxv.Multiply est devenu très chaud.

What Does the Java Virtual Machine Do All Day?

Dans la dernière répétition, le code de multiplication de la matrice utilise pleinement la machine virtuelle Java.

What Does the Java Virtual Machine Do All Day?

Figure 9: La dernière répétition du programme de multiplication de la matrice, montrant la configuration finale du code

Conclusion

J'ai montré la facilité d'arriver facilement à l'exécution des applications Java en utilisant GPROFNG pour l'analyse des performances. En utilisant la fonction de filtrage de GProfNG pour vérifier les expériences par Time Slice, j'ai pu vérifier les étapes du programme d'intérêt. Par exemple, l'exclusion de la phase d'allocation et d'initialisation de l'application et ne montrant qu'une répétition du programme lorsque le compilateur d'exécution exécute sa magie me permet de mettre en évidence les performances qui s'améliorent à mesure que le code chaud est progressivement compilé.

lecture plus approfondie

Pour les lecteurs qui souhaitent connaître GPROFNG, voici un article de blog avec des vidéos d'introduction sur GPROFNG, y compris des instructions sur la façon de l'installer sur Oracle Linux.

remerciements

Merci à Ruud van der Pas, Kurt Goebel et Vladimir Mezentsev pour leurs conseils et leur soutien technique, et à Elena Zannoni, David Banman, Craig Hardy et Dave Neary pour m'avoir encouragé à écrire ce billet de blog.

notes

  1. La motivation du composant de ligne de commande du programme est:
  • numactl --cpunodebind = 0 --mbind = 0 -. Limite la mémoire utilisée par les machines virtuelles Java au cœur et à la mémoire d'un nœud NUMA. Limiter le JVM à un nœud peut réduire la différence entre les programmes en cours d'exécution.
  • java. J'utilise la version OpenJDK de JDK-17.0.4.1 d'Aarch64.
  • -xx: useParallelgc. Activer le collecteur de déchets parallèles car il effectue un travail de fond minimal dans les collectionneurs disponibles.
  • -xms31g -xmx31g. Fournit suffisamment d'espace de tas d'objet Java et ne nécessite jamais de collecte de déchets.
  • -xlog: GC. Enregistrez les activités GC pour vérifier qu'il n'est vraiment pas nécessaire de collecter. ("Faites confiance mais vérifiez.")
  • -xx: -UserEperfdata. Réduisez les frais généraux des machines virtuelles Java.
  1. L'explication de l'option gprofng est:
  • -limit 24. Seules les 24 premières méthodes sont affichées (triées par temps de processeur exclusif ici). Je peux voir que montrer 24 méthodes me donne une bonne idée de ceux qui utilisent à peine le temps. Plus tard, j'utiliserai la limite 16 à certains endroits, où 16 méthodes peuvent réduire à celles qui contribuent le temps de processeur trivial. Dans certains exemples, Gprofng lui-même limite l'affichage, car il n'y a pas autant de méthodes qui accumulent le temps.
  • -ViewMode Expert. Ces méthodes qui affichent tout le temps de CPU cumulé, pas seulement les méthodes Java, y compris celles du JVM elle-même. L'utilisation de ce drapeau me permet de voir des méthodes de compilateur d'exécution, etc.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal