Profilage du code JavaScript : trouver les goulots d'étranglement pour les débutants

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

Profilage du code JavaScript : trouver les goulots d'étranglement

\n\n

Lorsque votre projet Node.js commence à ralentir, la première pensée est « il faut tout réécrire en Rust ». Mais ne vous précipitez pas ! Le plus souvent, le problème se cache dans quelques lignes de code qui fonctionnent de manière inefficace. Dans cet article, nous allons voir comment trouver ces « goulots d'étranglement » à l'aide d'outils de profilage simples. Vous apprendrez à mesurer les performances, à construire un flamegraph et à comprendre où va le CPU.

\n\n

Pourquoi profiler le code ?

\n\n

Imaginez que votre serveur traite 100 requêtes par seconde, alors qu'il en faut 500. Vous pouvez optimiser tout et n'importe quoi, mais cela prendra des semaines. Ou vous pouvez trouver une seule fonction qui s'exécute 80 % du temps et la corriger en une heure. Le profilage est exactement ce qui montre où le temps est dépensé.

\n\n

Examinons les principaux scénarios où le profilage est nécessaire :

\n
    \n
  • Latence élevée des réponses API
  • \n
  • Fuites mémoire (memory leaks)
  • \n
  • Charge CPU élevée sans raison apparente
  • \n
  • Traitement lent de grands tableaux de données
  • \n
\n\n

Outil 1 : Profileur intégré Node.js (--prof)

\n\n

La méthode la plus simple est de lancer Node.js avec le drapeau --prof. Il collecte des statistiques d'exécution et les enregistre dans un fichier isolate-*.log.

\n\n

Créons un script de test qui contient un goulot d'étranglement :

\n\n
// slow.js\nfunction heavyComputation() {\n    let sum = 0;\n    for (let i = 0; i < 1e7; i++) {\n        sum += Math.sqrt(i) * Math.sin(i);\n    }\n    return sum;\n}\n\nfunction fastFunction() {\n    return 42;\n}\n\nconsole.time('total');\nheavyComputation();\nfastFunction();\nconsole.timeEnd('total');\n
\n\n

Lançons le profilage :

\n
node --prof slow.js
\n\n

Après l'exécution, un fichier isolate-0x...-v8.log apparaît. Pour le lire, utilisons l'utilitaire node --prof-process :

\n
node --prof-process isolate-0x...-v8.log > profile.txt
\n\n

Ouvrons profile.txt et nous verrons un tableau avec des pourcentages de temps :

\n
[Summary]:\n   ticks  total  nonlib   name\n   785    78.5%  85.3%   JavaScript\n   215    21.5%  14.7%   C++\n   ...\n[Bottom up (heavy) profile]:\n  ticks parent  name\n   500   50.0%   LazyCompile: *heavyComputation slow.js:2:17\n   100   10.0%   Builtin: MathSqrt\n    50    5.0%   Builtin: MathSin\n
\n\n

Nous voyons que 50 % du temps est consacré à la fonction heavyComputation. Maintenant, nous savons quoi optimiser en premier.

\n\n

Outil 2 : Chrome DevTools (inspecteur)

\n\n

Pour une analyse plus visuelle, connectons Chrome DevTools. Lançons Node.js avec le drapeau --inspect :

\n
node --inspect slow.js
\n\n

Ouvrons Chrome et allons à l'adresse chrome://inspect. Cliquons sur « Open dedicated DevTools for Node ». Onglet « Profiler » → « Start » → lancez le script → « Stop ».

\n\n

Vous verrez un flamegraph — un graphique où la largeur du bloc montre le temps d'exécution. Plus le bloc est large, plus la fonction est « chaude ». Notre heavyComputation sera un énorme rectangle.

\n\n

Conseil : Utilisez le filtre « Focus selected » sur une fonction pour voir ses appels internes. Par exemple, vous remarquerez que Math.sqrt est appelé 10 millions de fois — il serait peut-être judicieux de calculer les racines à l'avance.

\n\n

Outil 3 : perf_hooks — mesures précises dans le code

\n\n

Parfois, il est nécessaire de mesurer une partie spécifique du code sans lancer d'outils externes. Pour cela, utilisons le module intégré perf_hooks.

\n\n

Exemple de mesure du temps d'exécution d'une fonction :

\n\n
const { performance } = require('perf_hooks');\n\nfunction processData(items) {\n    let result = [];\n    for (let item of items) {\n        // Simulation d'un traitement complexe\n        for (let j = 0; j < 1000; j++) {\n            result.push(item * j);\n        }\n                

Blogs

Book Recommendations