Profilage du code Rust : trouver les goulots d'étranglement en pratique

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 Rust : trouver les goulots d'étranglement en pratique

\n\n

Rust est réputé pour ses performances, mais même le code le plus rapide peut contenir des goulots d'étranglement inattendus. Le profilage est l'art et la science de l'identification de ces problèmes. Dans cet article, nous allons voir en pratique comment trouver et éliminer les « goulots d'étranglement » dans les applications Rust, en utilisant des outils et techniques modernes.

\n\n

Pourquoi le profilage est-il important pour Rust ?

\n\n

Bien que Rust garantisse l'absence de ramasse-miettes et offre un contrôle de bas niveau sur la mémoire, cela ne protège pas contre les algorithmes inefficaces, les allocations superflues ou une mauvaise utilisation du cache. Sans profilage, vous risquez d'optimiser ce qui ne doit pas l'être. Le profilage répond aux questions suivantes :

\n\n
    \n
  • Quelles fonctions consomment le plus de CPU ?
  • \n
  • Où se produisent les allocations mémoire fréquentes ?
  • \n
  • Quelles parties du code bloquent l'exécution (par exemple, à cause de mutex) ?
  • \n
  • Dans quelle mesure le cache du processeur est-il utilisé efficacement ?
  • \n
\n\n

Outils pour le profilage Rust

\n\n

Examinons trois approches principales qui couvrent 90 % des tâches de profilage.

\n\n

1. Benchmarking intégré avec cargo bench

\n\n

La méthode la plus simple consiste à utiliser cargo bench de l'écosystème Rust. Il permet de mesurer le temps d'exécution de fonctions individuelles.

\n\n

Exemple de benchmark pour une fonction triant un vecteur :

\n\n
// benches/my_bench.rs\nuse criterion::{black_box, criterion_group, criterion_main, Criterion};\n\nfn sort_benchmark(c: &mut Criterion) {\n    let mut data: Vec<i32> = (0..10000).rev().collect();\n\n    c.bench_function("sort 10k", |b| {\n        b.iter(|| {\n            // black_box empêche l'optimisation du compilateur\n            let mut clone = black_box(data.clone());\n            clone.sort();\n            black_box(clone)\n        })\n    });\n}\n\ncriterion_group!(benches, sort_benchmark);\ncriterion_main!(benches);
\n\n

Exécution : cargo bench

\n\n

Vous obtiendrez un rapport avec le temps, l'écart type et la comparaison avec les exécutions précédentes. C'est idéal pour les tests de régression de performance.

\n\n

2. Profileur système perf (Linux)

\n\n

perf est un outil puissant du noyau Linux. Il collecte des échantillons de compteurs de performance (cycles CPU, défauts de cache, instructions) sans modification du code.

\n\n

Utilisation de base :

\n\n
# Collecte de données\nperf record -F 99 --call-graph dwarf ./my_rust_program\n\n# Visualisation du rapport\nperf report --stdio\n\n# Génération d'un flamegraph\nperf script | stackcollapse-perf.pl | flamegraph.pl > flame.svg
\n\n

Le drapeau -F 99 définit la fréquence d'échantillonnage à 99 Hz (généralement suffisant). --call-graph dwarf active l'enregistrement de la pile d'appels. En sortie, vous obtenez un flamegraph interactif (SVG), où l'axe X représente le temps et l'axe Y la pile d'appels. La largeur du rectangle indique le temps passé dans la fonction.

\n\n

3. L'outil flamegraph pour Rust

\n\n

Il existe un utilitaire spécialisé cargo-flamegraph qui simplifie la création de flamegraphs pour les projets Rust :

\n\n
cargo install flamegraph\ncargo flamegraph --bin my_binary
\n\n

Après exécution, un fichier flamegraph.svg apparaît à la racine du projet. Ouvrez-le dans un navigateur — vous verrez immédiatement les parties « chaudes » du code.

\n\n

Exemple pratique : optimisation d'un analyseur syntaxique

\n\n

Imaginons que nous écrivions un analyseur JSON en Rust, et qu'il soit lent. Utilisons le profilage pour trouver le problème.

\n\n

Étape 1 : Benchmark

\n\n

Créons un benchmark pour analyser un gros fichier JSON (par exemple, 10 Mo). Exécutons cargo bench et voyons que l'analyse prend 2,5 secondes. C'est beaucoup.

\n\n

Étape 2 : Flamegraph

\n\n

Lançons cargo flamegraph sur le binaire qui analyse ce fichier. Ouvrons le SVG et voyons que 60 % du temps

Blogs

Book Recommendations