Mozilla's getting a new look. What do you think? https://mzl.la/brandsurvey

Arbre d'appels

L'arbre d'appel permet de savoir dans quelles fonctions JavaScript le navigateur passe le plus de temps. En analysant ces résultats, il est possible de trouver les points noirs du code (les endroits ou le navigateur passe beaucoup trop de temps).

Ces points noirs sont les endroits où les optimisations auront le plus grand impact.

L'arbre d'appel est un profileur par échantillons. Il prend périodiquement des échantillons de l'état du moteur JavaScript, et enregistre la pile pour le code s'exécutant dans ce moment. Statistiquement, le nombre d'échantillons dans lequel on exécute une fonction en particulier correspond au temps que le navigateur passe à l'exécuter. Il est alors possible de trouver les points noirs de votre code.

Cet article utilisera le résultat d'un programme simple comme exemple. Si vous voulez récupérer ce programme pour expérimenter l'outil vous-même, il est disponible ici. Vous pouvez trouver le profil discuté dans cet article ici - importez juste le profil dans l'outil Performance pour pouvoir voir le profil utilisé dans cet article.

Il y a une courte page décrivant la structure du programme disponible ici.

Il est à noter que le même programme et le même profil est utilisé pour la page de documentation sur le Flame Chart.

La capture d'écran ci-dessous montre les résultats d'un programme qui compare trois différents algorithmes de tri (tri à bulle, tri par sélection et tri rapide). Pour faire cela, il génère un nombre de tableaux remplis avec des int aléatoires et les tris avec chaque algorithme.

Nous avons zoomé dans une partie de l'enregistrement qui montre un long marker JavaScript :

L'arbre d'appel présente les résultats dans un tableau. Chaque ligne représente une fonction dans laquelle au moins un échantillon a été pris, et les lignes sont classées par nombre d'échantillons pris dans la fonction.

Échantillons correspond au nombre d'échantillons pris lors de de l'exécution de la fonction.

Cout individuel correspond au pourcentage d'échantillons de la fonction par rapport au nombre total d'échantillons dans l'enregistrement.

Durée individuelle correspond au nombre d'échantillons traduit en millisecondes, basées sur le temps total passé par la portion de l'enregistrement sélectionnée.

Dans la version actuelle de l'arbre d'appel, ce sont les colones les plus importantes. Les fonctions avec un Cout individuel important sont de bons candidats pour de l'optimisation, soit parce qu’elles prennent beaucoup de temps à s'exécuter, soit parce qu'elles sont appelées très souvent.

Cette capture d'écran révèle ce que l'on savait déjà : le tri à bulles est un algorithme très inefficace. Il y a à peu près 6 fois plus d'échantillons dans le tri à bulle que de dans le tri à sélection, et 13 fois plus dans que dans le tri rapide.

Se déplacer dans l'arbre d'appel

A coté de chaque nom de fonction, se trouve une flèche d'expansion : cliquer sur celle-ci révèle le chemin allant de l'appel de la fonction jusqu'a la racine. Par exemple, il est possible d'étendre l'entrée pour bubbleSort() :

On peut donc voir que le graphique d'appel est comme ceci :

sortAll()

    -> sort()

        -> bubbleSort()

Notez également que le Cout individuel pour sort() est ici de 1.45%, et notez également que ce chiffre est le même pour une autre ligne de sort() plus tard dans la liste. Cela révèle que quelques échantillons ont été pris dans sort() elle-même plutôt que dans la fonction qu'elle appelle.

Quelques fois, il y a plus d'un chemin menant à la même fonction. Essayons par exemple d'étendre la ligne de swap():

Il y a 253 échantillons qui ont été pris à l'intérieur de swap(). Mais swap() a été accédé par deux chemins différents car bubbleSort() et selectionSort() l'utilisent tous deux. Il est également possible de voir que 252 des 253 échantillons ont été pris dans la branche bubbleSort(), et uniquement un dans la branche selectionSort().

Cela signifie que le tri à bulle est encore moins efficient que ce que l'on pensait ! La fonction coute 252 échantillons de plus, soit 10% de cout supplémentaire.

Avec ce genre de recherche, il est possible de déduire le graphique d'appel complet, avec le nombre d'échantillons associés :

sortAll()                         //    8

    -> sort()                     //   37

        -> bubbleSort()           // 1345

            -> swap()             //  252

        -> selectionSort()        //  190

            -> swap()             //    1

        -> quickSort()            //  103

            -> partition()        //   12

Données de la plateforme

Vous pouvez également remarquer des lignes nommées Gecko, Input & Events, et ainsi de suite. Cela représente les appels internes au navigateur.

Cela peut être utile comme informations. Par exemple si votre site donne beaucoup de travail au navigateur. Ces échantillons ne sont peut-être pas pris dans votre code, mais c'est quand même votre problème.

Dans notre exemple, il y a 679 échantillons assignés à Gecko - le deuxième plus gros groupe après bubbleSort(). étendons donc cela :

Cela révèle que 614 de ces échantillons, soit environ 20% du cout total, viennent de l'appel de sort(). Si nous regardons au code de la fonction, il devient évident que le cout élevé des données de plateforme viennent des appels répétés à console.log():

function sort(unsorted) {
  console.log(bubbleSort(unsorted));
  console.log(selectionSort(unsorted));
  console.log(quickSort(unsorted));
}

Il serait certainement intéressant de considérer des façons plus efficientes d'implémenter cela.

Une chose à garder en tête est que les périodes d'inactivité sont classifiées en tant que Gecko, donc les parties de votre profil où votre JavaScript ne tourne pas contribueront aux échantillons Gecko. Ces échantillons n'impactent pas la performance de votre site.

Par défaut, l'arbre d'appel ne sépare par les données de plateforme dans des fonctions séparées, car elles ajoutent beaucoup de nuisance et ces détails ont peu de chances d'être utiles à des personnes ne travaillant sur le développement de Firefox. Si vous voulez cependant voir ces détails, il faut cocher l'option "Afficher les données de la plateforme Gecko" dans les options.

Étiquettes et contributeurs liés au document

 Contributeurs à cette page : maximelore
 Dernière mise à jour par : maximelore,