Concepts du profilage
Le profilage est une forme d'analyse de code dynamique Vous capturez les caractéristiques de l'application au cours de son exécution, puis vous consultez ces informations pour déterminer comment rendre votre application plus rapide et plus efficace.
Auparavant, le profilage ne s'effectuait que lors du développement d'applications. Cette approche s'appuyait sur la capacité à développer des tests de charge et des analyses comparatives permettant de prédire avec précision un environnement de production.
Le profilage continu consiste à profiler l'application au cours de son exécution dans un environnement de production. Avec cette méthode, vous n'avez pas besoin de développer de tests de charge prédictifs et précis ni d'analyses comparatives pour l'environnement de production. Une étude sur le profilage continu a montré qu'il s'agit d'une méthode précise et économique *.
Cloud Profiler est un outil de profilage continu conçu pour les applications exécutées sur Google Cloud :
Il s'agit d'un profileur statistique ou d'échantillonnage, qui présente des coûts faibles et convient aux environnements de production.
Il est compatible avec les langages courants et recueille plusieurs types de profils. Pour en savoir plus, consultez la section Types de profilages disponibles.
La configuration d'une application Google Cloud pour générer des données de profil est un processus simple et unique. Vous associez ou exécutez votre service avec un agent de profilage inclus. Une fois l'application déployée, l'agent de profilage s'exécute régulièrement pour recueillir des données de performance, qu'il envoie ensuite à votre projet Google Cloud. Pour en savoir plus sur ce processus, consultez la section Collecter des profils.
Une fois les données de profil de votre application recueillies, vous pouvez les analyser à l'aide de l'interface de Profiler. En général, l'analyse des données de profil est un processus itératif, qui repose sur votre connaissance de la conception de l'application et de son langage de programmation.
*Consultez les articles suivants : Google-Wide Profiling: A Continuous Profiling Infrastructure for Data Centers (Profilage à l'échelle de Google : une infrastructure de profilage continu pour les centres de données) et Continuous Profiling: Where Have All the Cycles Gone? (Profilage continu : où sont passés les cycles ?).
Types de profilage disponibles
Le tableau ci-dessous récapitule les types de profils compatibles :
Type de profil | Go | Java | Node.js | Python |
---|---|---|---|---|
Temps CPU | O | O | O | |
Segment de mémoire | O | O | O | |
Tas de mémoire alloué | O | |||
Contention | O | |||
Threads | O | |||
Durée d'exécution | O | O | O |
Le reste de cette section contient des informations supplémentaires sur chaque type de profil.
Mesures de temps
Le temps CPU est le temps que le processeur passe à exécuter un bloc de code.
Le temps CPU d'une fonction indique la durée pendant laquelle le processeur a exécuté des instructions. Il n'inclut pas le temps d'attente du processeur ni le temps de traitement d'instructions consacré à un autre élément.
La durée d'exécution (également appelée durée réelle) est le temps nécessaire pour exécuter un bloc de code.
La durée d'exécution d'une fonction est le temps qui s'est réellement écoulé entre l'entrée et la sortie de celle-ci. La durée d'exécution inclut tous les temps d'attente, y compris ceux des verrous et de la synchronisation des threads. La durée d'exécution d'un bloc de code ne peut jamais être inférieure au temps CPU.
Si la durée d'exécution est supérieure au temps CPU, le code passe du temps à attendre. Lorsque la différence est importante, votre application peut présenter un goulot d'étranglement au niveau des ressources.
Si le temps CPU est semblable à la durée d'exécution, cela indique que le code est gourmand en ressources processeur. La majeure partie du temps nécessaire à l'exécution est utilisée par le processeur. Les blocs de code de longue durée, qui utilisent beaucoup de ressources processeur, peuvent être optimisés.
Utilisation du segment (mémoire)
L'utilisation des segments de mémoire (également appelée tas de mémoire) correspond à la quantité de mémoire allouée dans le tas de mémoire du programme au moment où le profil est collecté. Contrairement aux autres types de profils dans lesquels les données sont collectées sur un intervalle, ce type de profil collecte l'utilisation des segments de mémoire à un moment précis.
Allocation de segments de mémoire (également appelée tas de mémoire alloué) est la quantité totale de mémoire allouée dans le tas de mémoire du programme durant l'intervalle au cours duquel le profil a été collecté. Cette valeur inclut toute mémoire allouée et libérée qui n'est plus utilisée. Prenons l'exemple d'une tâche qui répète la séquence suivante : attribue 1 Mio, attend 500 ms, libère 1 Mio, attend 500 ms. Au cours des 10 secondes au cours desquelles le profil de tas de mémoire est collecté, 10 allocations et 10 libérations sont comptabilisées. Ce profil affiche un tas de mémoire alloué de 10 Mio, car les libérations ne sont pas prises en compte. Le taux d'allocation moyen est de 10 Mio/10 secondes ou de 1 Mio par seconde.
Grâce au profilage de l'utilisation de tas de mémoire, vous pouvez détecter les sources d'inefficacité potentielles et les fuites de mémoire dans vos programmes. Quant au profilage des allocations de segments de mémoire, il vous permet de savoir quelles allocations augmentent la charge de travail du récupérateur de mémoire.
Informations sur les threads
Les applications qui créent des threads peuvent subir des défaillances provoquées par des blocages ou des fuites au niveau des threads :
- Les threads bloqués sont des threads créés, mais qui attendent un verrouillage. Ces threads ne sont pas en cours d'exécution et ne le seront peut-être jamais. Toutefois, un thread bloqué peut éventuellement s'exécuter.
- Les fuites de threads se produisent lorsque le nombre de threads créés ne cesse d'augmenter.
Les threads bloqués sont l'une des causes de fuites de threads.
Au niveau du frame, le profil Thread (Fil) affiche le nombre moyen de threads qui incluent ce frame. Ce type de profil collecte l'utilisation des threads à un moment précis.
Contention
Dans un programme à plusieurs threads, le temps d'attente nécessaire à la sérialisation de l'accès à une ressource partagée peut être important. La compréhension du comportement de contention peut guider la conception du code et fournir des informations utiles pour le réglage des performances.
Collecter des profils
Le rôle de l'agent de profilage est de capturer les données de profil de votre application et de les transmettre au backend de Profiler à l'aide de l'API Profiler. Chaque profil correspond à une seule instance d'une application et comprend quatre champs permettant d'identifier son déploiement de manière unique :
- Projet Google Cloud
- Nom de l'application
- Zone de l'application
- Version de l'application
Lorsqu'un agent est prêt à collecter un profil, il envoie une commande de l'API Profiler au backend de Profiler. Le backend reçoit cette requête et, dans le scénario le plus simple, répond immédiatement à l'agent. Cette réponse spécifie le type de profil à collecter. En conséquence, l'agent collecte le profil et le transmet au backend. Enfin, le backend de Profiler associe le profil à votre projet Google Cloud. Vous pouvez ensuite l'afficher et l'analyser à l'aide de l'interface de Profiler.
La séquence de handshake réelle est plus complexe que celle décrite dans le paragraphe précédent. Par exemple, lorsque Profiler reçoit une requête d'un agent, le backend analyse sa base de données pour déterminer s'il a déjà reçu des requêtes de cet agent. S'il n'en a jamais reçu, le backend ajoute les informations sur l'agent à sa base de données. Un nouveau déploiement est créé si les champs de déploiement de l'agent ne correspondent à aucun des paramètres d'un autre agent enregistré.
Chaque minute, en moyenne, et ce, pour chaque déploiement et pour chaque type de profil, le backend sélectionne un agent et lui demande de collecter un profil. Par exemple, si les agents d'un déploiement sont compatibles avec le profilage de tas de mémoire et de durée d'exécution, deux profils sont collectés en moyenne chaque minute :
Pour tous les types de profils, à l'exception de l'utilisation des segments de mémoire et des threads, un seul profil représente les données collectées pendant 10 secondes.
Les profils des segments de mémoire et des threads sont collectés instantanément.
Une fois que l'agent a indiqué au backend de Profiler qu'il était prêt à collecter des données, l'agent reste inactif jusqu'à ce qu'il reçoive une réponse du backend spécifiant le type de profil à collecter. Si 10 instances d'une application s'exécutent dans le même déploiement, vous créez 10 agents de profilage. Toutefois, la plupart du temps, ces agents sont inactifs. Sur une période de dix minutes, vous pouvez vous attendre à dix profils. Chaque agent reçoit une réponse pour chaque type de profil, en moyenne. En raison d'une certaine randomisation impliquée, le nombre réel peut varier.
Le backend de Profiler se sert des quotas de l'API Profiler et des champs de déploiement du profil pour limiter les profils ingérés. Pour en savoir plus sur l'affichage et la gestion des quotas de Profiler, consultez la page Quotas et limites.
Analyse des données
Une fois que Profiler a collecté des données, vous pouvez les afficher et les analyser dans son interface.
Dans la console Google Cloud, accédez à la page Profiler:
Vous pouvez également accéder à cette page à l'aide de la barre de recherche.