Principes de base et bonnes pratiques de «JProfiler», un outil de diagnostic des performances Java représentatif

Cet article décrit certains outils de diagnostic des performances ** Java ** courants et met en évidence les principes de base et les meilleures pratiques de ** JProfiler **.

Contexte

Les diagnostics de performance sont un problème auquel les ingénieurs logiciels sont souvent confrontés et qu'ils doivent résoudre dans leur travail quotidien. Vous pouvez obtenir de grands avantages en améliorant les performances de votre application. Java est l'un des langages de programmation les plus populaires. Ses diagnostics de performance ont longtemps été au centre de l'attention dans toute l'industrie. Dans les applications Java, de nombreux facteurs peuvent entraîner des problèmes de performances. Ces facteurs incluent le contrôle des threads, les E / S disque, l'accès à la base de données, les E / S réseau et le garbage collection (GC). Pour trouver ces problèmes, vous avez besoin d'un bon outil de diagnostic des performances. Cet article décrit certains outils de diagnostic des performances Java populaires et est représentatif de ces outils [JProfiler](https://www.ej-technologies.com/products/jprofiler/overview.html? Présentation des principes de base et des meilleures pratiques de spm = a2c65.11461447.0.0.4e294d65AIiUSB). La version de JProfiler présentée dans cet article est «JProfiler10.1.4».

Une brève introduction aux outils de diagnostic des performances Java

Il existe une variété d'outils de diagnostic des performances dans le monde Java, des simples outils de ligne de commande tels que jmap et jstat aux outils de diagnostic graphiques complets tels que JVisualvm et JProfiler. Les sections suivantes décrivent brièvement chacun de ces outils.

Outil de ligne de commande simple

Le kit de développement Java (JDK) fournit de nombreux outils de ligne de commande intégrés. Ces outils vous aident à obtenir des informations sur la machine virtuelle Java cible (JVM) sous différents aspects et différentes couches.

--jinfo - Vous pouvez afficher et ajuster divers paramètres de la JVM cible en temps réel. --jstack - Vous pouvez obtenir des informations sur la pile de threads pour le processus Java cible, détecter les blocages et trouver des boucles infinies. --jmap - Obtient des informations relatives à la mémoire pour le processus Java cible. Cela inclut différentes utilisations du tas Java, des statistiques sur les objets du tas Java, des classes chargées, etc. --jstat --Un outil de surveillance léger et polyvalent. Vous pouvez obtenir de nombreuses informations sur les classes chargées du processus Java cible, la compilation juste-à-temps (JIT), le garbage collection et l'utilisation de la mémoire. --jcmd --Complet que jstat. Vous pouvez obtenir diverses informations sur les statistiques de performances des processus Java cibles, l'enregistreur de vol Java (JFR), l'utilisation de la mémoire, le garbage collection, l'empilement des threads et le runtime JVM.

Outil de diagnostic graphique complet

Vous pouvez utiliser tout ou partie des outils de ligne de commande ci-dessus pour obtenir des informations de base sur les performances de votre application Java cible. Cependant, ces outils présentent les inconvénients suivants:

  1. Il n'est pas possible d'obtenir des données d'analyse au niveau de la méthode, telles que la relation d'appel entre différentes méthodes et la fréquence et la durée des appels de méthode. Ils sont très importants pour identifier les goulots d'étranglement des performances des applications.
  2. Pour les utiliser, vous devez vous connecter à la machine hôte de l'application Java cible, ce qui n'est pas très pratique.
  3. Les données d'analyse sont générées sur le terminal et le résultat n'est pas affiché.

Vous trouverez ci-dessous quelques outils de diagnostic des performances graphiques complets.

JVisualvm JVisualvm est un diagnostic de performance visuelle intégré fourni par JDK. C'est un outil. Utilisez diverses méthodes telles que JMX, jstatd et Attach API pour acquérir des données d'analyse de la JVM cible, telles que l'utilisation du processeur, l'utilisation de la mémoire, le nombre de threads, le nombre de segments de mémoire et le nombre de piles. Vous pouvez également afficher la quantité et la taille de chaque objet dans le tas Java, le nombre d'appels de méthode Java, le temps d'exécution de la méthode Java, etc.

JProfiler JProfiler est un outil de diagnostic des performances pour les applications Java développé par ej-technologies. Il se concentre sur quatre sujets importants.

  1. Appels de méthode - L'analyse des appels de méthode peut vous aider à comprendre ce que fait votre application et à trouver des moyens d'améliorer les performances. 2, analyse par allocation des objets, chaînes de référence et garbage collection sur le tas, cette fonctionnalité vous permet de corriger les fuites de mémoire et d'optimiser l'utilisation de la mémoire.
  2. Threads and Locks-JProfiler fournit plusieurs vues d'analyse sur les threads et les verrous pour vous aider à découvrir les problèmes de multithreading. 4, sous-système de haut niveau - De nombreux problèmes de performances se produisent à des niveaux sémantiques plus élevés. Par exemple, dans un appel JDBC (Java Database Connectivity), vous souhaiterez peut-être savoir quelle instruction SQL est la plus lente. JProfiler prend en charge l'analyse intégrée de ces sous-systèmes.

Diagnostic distribué des performances des applications

Si vous souhaitez simplement diagnostiquer un goulot d'étranglement des performances dans une application Java autonome, les outils de diagnostic ci-dessus sont suffisants pour répondre à vos besoins. Cependant, à mesure que les systèmes autonomes modernes évoluent progressivement vers des systèmes distribués et des microservices, les outils ci-dessus ne répondront plus aux exigences. Par conséquent, Jaeger et [ARMS](https://cn.aliyun.com/product/arms?spm=a2c65. Vous devez profiter des capacités de traçage de bout en bout des systèmes de traçage distribués tels que 11461447.0.0.4e294d65AIiUSB) et SkyWalking. Divers systèmes de traçage distribués sont disponibles dans le commerce, mais le mécanisme de mise en œuvre est similaire. Il enregistre les informations de trace par suivi de code, envoie les données enregistrées au système de traitement central via le SDK ou l'agent, et fournit une interface de requête pour afficher et analyser les résultats. Pour plus d'informations sur les principes des systèmes de traçage distribués, consultez l'article intitulé Jaeger's Open Tracing Implementation.

Introduction de JProfiler

Composants principaux

JProfiler se compose d'un agent JProfiler pour collecter les données d'analyse de la JVM cible, d'une interface utilisateur JProfiler pour analyser visuellement les données et d'un utilitaire de ligne de commande qui fournit diverses fonctions. Voici un aperçu complet des interactions importantes entre eux.

image.png

Agent JProfiler

L'agent JProfiler est implémenté en tant que bibliothèque native. Chargez au moment de l'exécution lorsque la JVM démarre en utilisant le paramètre -agentpath: <chemin vers la bibliothèque native> ou [JVM Attach Mechanism](http://lovestblog.cn/blog/2014/06/18/jvm-attach/?spm = a2c65.11461447.0.0.4e294d65AIiUSB) peut être utilisé pour charger pendant que l'application est en cours d'exécution. Une fois l'agent JProfiler chargé, il configure l'environnement JVM Tools Interface (JVMTI) pour surveiller tous les types d'événements générés par la JVM, comme la création de threads et le chargement de classes. Par exemple, lorsqu'il détecte un événement de chargement de classe, l'agent JProfiler insère son propre bytecode dans ces classes pour effectuer la mesure.

JProfiler UI L'interface utilisateur de JProfiler est lancée individuellement et se connecte à l'agent de profilage via un socket. Autrement dit, peu importe si la JVM profilée s'exécute sur la machine locale ou sur une machine distante - le mécanisme de communication entre l'agent de profilage et l'interface utilisateur de JProfiler est toujours le même.

À partir de l'interface utilisateur de JProfiler, vous pouvez demander à l'agent d'enregistrer des données, d'afficher les données de profilage dans l'interface utilisateur et d'enregistrer les instantanés sur le disque.

Outil de ligne de commande

JProfiler fournit un ensemble d'outils de ligne de commande pour implémenter diverses fonctionnalités.

--jpcontroller - Utilisé pour contrôler la manière dont l'agent collecte les données. Envoyez des instructions à l'agent via le MBean JProfiler enregistré par l'agent. --jpenable - Utilisé pour charger l'agent dans une JVM en cours d'exécution. --jpdump - Utilisé pour capturer un instantané de tas d'une JVM en cours d'exécution. --jpexport & jpcompare - Utilisé pour extraire les données des instantanés précédemment enregistrés et créer des rapports HTML.

Installation

JProfiler prend en charge les diagnostics de performances pour les applications Java locales et distantes. Si vous avez besoin de collecter et d'afficher des données d'analyse pour une machine virtuelle Java distante en temps réel, procédez comme suit:

  1. Installez l'interface utilisateur de JProfiler localement.
  2. Installez l'agent JProfiler sur la machine hôte distante et chargez-le sur la JVM cible.
  3. Connectez l'interface utilisateur de JProfiler à l'agent.

Pour plus de détails sur la procédure d'installation, consultez «Installation de JProfiler» et «[JVM Voir Profilage (https://www.ej-technologies.com/resources/jprofiler/help/doc/main/introduction.html#jprofiler.profiling).

meilleur entrainement

Ici, les performances de la bibliothèque de classes LogHub Alibaba Cloud LOG Java Producer (ci-après, Producteur) Je vais vous montrer comment diagnostiquer avec JProfiler. Si vous rencontrez des problèmes de performances lors de l'utilisation de votre application ou Producer, vous pouvez prendre des mesures similaires pour trouver la cause première. Si vous êtes nouveau dans Producer, nous vous recommandons de lire cet article en premier. Alibaba Cloud LOG Java Producer - Un outil puissant pour la migration des journaux vers le cloud.

L'exemple de code utilisé ici est [SamplePerformance.java](https://github.com/aliyun/aliyun-log-producer-sample/blob/master/src/main/java/com/aliyun/openservices/aliyun/log /producer/sample/SamplePerformance.java?spm=a2c65.11461447.0.0.4e294d65AIiUSB&file=SamplePerformance.java).

Paramètres de JProfiler

Mode de collecte de données

JProfiler a deux méthodes de collecte de données: l'échantillonnage et la mesure.

--Échantillonnage --Convient aux scénarios qui ne nécessitent pas une grande précision de collecte de données. L'avantage de cette méthode est qu'elle a moins d'impact sur les performances du système. L'inconvénient est que certaines fonctionnalités, telles que les statistiques au niveau de la méthode, ne sont pas prises en charge. --Instrumentation - Un mode de collecte de données complet qui prend en charge une haute précision. Les inconvénients sont que de nombreuses classes doivent être analysées et l'impact sur les performances de l'application est relativement important. Pour réduire l'impact, il est recommandé de l'utiliser avec un filtre. Dans cet exemple, nous devons obtenir des statistiques au niveau de la méthode, nous choisissons donc la méthode d'instrumentation. Le filtre est configuré de manière à ce que l'agent enregistre les données du processeur pour seulement deux classes sous le package java: com.aliyun.openservices.aliyun.log.producer et com.aliyun.openservices.log.Client. Je suis.

Mode de lancement de l'application

Vous pouvez spécifier divers paramètres à l'agent JProfiler pour contrôler le mode de lancement de l'application.

--Attendez une connexion depuis l'interface graphique JProfiler --L'application ne se lancera que si l'interface graphique JProfiler établit une connexion avec l'agent de profilage et complète les paramètres de profilage. Cette option vous permet de profiler la phase de lancement de votre application. Commandes pouvant être utilisées pour activer cette option: -agentpath: <chemin vers la bibliothèque native> = port = 8849

Dans un environnement de test, vous devez déterminer les performances de votre application pendant la phase de lancement. Par conséquent, nous utiliserons ici l'option par défaut WAIT.

Diagnostiquer les performances des applications à l'aide de JProfiler

Une fois que vous avez configuré votre profilage, vous pouvez procéder au diagnostic des performances du producteur.

Aperçu

Sur la page de présentation, vous pouvez voir clairement les graphiques (télémétrie) de diverses mesures telles que la mémoire, l'activité du GC, les classes, les threads et la charge du processeur.

image.png

Sur la base de cette télémétrie, nous pouvons faire les hypothèses suivantes:

  1. Un grand nombre d'objets sont créés pendant l'exécution de l'application. Le cycle de vie de ces objets est très court et la plupart des objets sont rapidement recyclés par le ramasse-miettes. Ces objets ne provoquent pas une augmentation continue de l'utilisation de la mémoire.
  2. Comme prévu, le nombre de classes chargées augmente rapidement pendant la période de démarrage puis se stabilise.
  3. De nombreux threads sont bloqués pendant l'exécution de l'application. Une attention particulière doit être portée à ce problème.
  4. Au démarrage de l'application, l'utilisation du processeur sera élevée. Nous devons découvrir la cause.

Vue CPU

Le nombre d'exécutions, le temps d'exécution et les relations d'appel de chaque méthode dans l'application sont affichés dans la vue CPU. Ceux-ci vous aideront à trouver les méthodes qui ont le plus d'impact sur les performances de votre application.

Arbre d'appel

L'arbre d'appels utilise un graphe d'arbre pour afficher de manière hiérarchique les relations d'appels entre les différentes méthodes. De plus, JProfiler trie les sous-méthodes par durée totale d'exécution, afin que vous puissiez trouver rapidement les méthodes clés.

image.png

Pour Producer, la méthode SendProducerBatchTask.run () prend la plupart du temps à s'exécuter. Si vous continuez à regarder vers le bas, vous pouvez voir que la plupart du temps il faut pour exécuter la méthode Client.PutLogs ().

Point chaud

Si vous disposez de nombreuses méthodes d'application et que de nombreuses sous-méthodes s'exécutent à de courts intervalles, vous pouvez utiliser la vue hotspot pour trouver rapidement les problèmes de performances. Cette vue vous permet de trier les méthodes en fonction de divers facteurs tels que le temps d'exécution individuel, le temps total d'exécution, le temps d'exécution moyen et le nombre d'appels. Le temps d'exécution individuel est le temps d'exécution total de la méthode moins le temps d'exécution total de toutes les sous-méthodes.

image.png

Dans cette vue, vous pouvez voir que les trois méthodes suivantes sont les plus lentes à exécuter: Vous pouvez voir que les trois méthodes «Client.PutLogs ()», «LogGroup.toByteArray ()» et «SamplePerformance $ 1.run ()» prennent le plus de temps à s'exécuter individuellement.

Graphique d'appel

Après avoir trouvé les méthodes clés, vous pouvez afficher toutes les méthodes directement liées à ces méthodes clés dans la vue graphique des appels. Cela vous aidera à trouver une solution à votre problème et à développer la meilleure politique d'optimisation des performances.

image.png

Ici, vous pouvez voir que la plupart du temps d'exécution de la méthode Client.PutLogs () est passé à sérialiser l'objet. Par conséquent, la clé de l'optimisation des performances est de fournir une méthode de sérialisation plus efficace.

Mémoire en direct

La vue Live Memory vous donne une allocation et une utilisation détaillées de la mémoire, ce qui peut vous aider à déterminer s'il y a une fuite de mémoire.

All Objects La vue Tous les objets affiche le nombre et la taille totale des différents objets du tas actuel. Comme vous pouvez le voir dans la figure suivante, de nombreux objets LogContent sont créés pendant l'exécution de l'application.

image.png

Allocation Call Tree La vue de l'arborescence des appels d'allocation montre la quantité de mémoire allouée à chaque méthode sous la forme d'un diagramme arborescent. Comme vous pouvez le voir, «SamplePerformance $ 1.run ()» et «SendProducerBatchTask.run ()» consomment beaucoup de mémoire.

image.png

Allocation Hot Spots Si vous disposez de nombreuses méthodes, vous pouvez voir rapidement quelle méthode a le plus d'objets affectés dans la vue Points sensibles d'allocation.

Thread History La vue Historique des threads affiche l'état de chaque thread à des moments différents.

image.png

Les tâches exécutées par différents threads ont des caractéristiques différentes.

--Thread Pool-1-thread- <M> appelle périodiquement la méthodeProducer.send ()pour envoyer des données de manière asynchrone. Ceux-ci ont continué à s'exécuter pendant que l'application était en cours d'exécution, mais la plupart d'entre eux ont été bloqués par la suite. La cause de ce comportement est que la vitesse de transmission des données de Producer est plus lente que la vitesse de génération de données et que la taille du cache de chaque instance de Producer est limitée. Après le lancement de l'application, pool-1-thread- <M> est resté en cours d'exécution pendant un certain temps car Producer avait suffisamment de mémoire pour mettre en cache les données en attente d'envoi. Cela explique pourquoi l'utilisation du processeur était élevée au lancement de l'application. pool-1-thread- <M> doit attendre que le producteur libère suffisamment d'espace. En conséquence, un grand nombre de threads sont bloqués.

--ʻAliyun-log-Producer-0-moverdétecte les lots expirés et les envoie à iothreadPool. La vitesse d'accumulation des données est rapide et le lot producteur est envoyé à IOThreadPool parpool-1-thread- ` immédiatement après que la taille des données mises en cache a atteint la limite supérieure. En conséquence, le thread de déplacement est resté inactif la plupart du temps.

--ʻAliyun-log-Producer-0-io-thread- Envoie les données d'IOThreadPool au magasin de journaux spécifié et passe la plupart du temps sur l'état des E / S du réseau. --ʻAliyun-log-Producer-0-success-batch-handler traite les lots envoyés avec succès au magasin de journaux. Le rappel est simple et prend très peu de temps à exécuter. Par conséquent, SuccessBatchHandler est resté inactif la plupart du temps. --ʻAliyun-log-Producer-0-failure-batch-handler` gère les lots qui ne parviennent pas à être envoyés au magasin de journaux. Dans notre cas, il n'y a aucune donnée qui n'a pas pu être envoyée. Il est resté inactif tout le temps. Selon notre analyse, le statut de ces fils est conforme à nos attentes.

Point d'accès au-dessus détecté

Une fois l'application terminée, JProfiler affiche une boîte de dialogue qui affiche les méthodes fréquemment appelées avec des temps d'exécution très courts. La prochaine fois, vous pourrez atténuer l'impact de JProfiler sur les performances des applications en configurant l'agent JProfiler pour ignorer ces méthodes.

image.png

Aperçu

Sur la base des diagnostics de JProfiler, l'application n'a pas de problèmes de performances majeurs ni de fuites de mémoire. La prochaine étape d'optimisation consiste à améliorer l'efficacité de la sérialisation des objets.

Les références

Recommended Posts

Principes de base et bonnes pratiques de «JProfiler», un outil de diagnostic des performances Java représentatif
[Java] Résumé personnel des classes et méthodes (basique)