Perf
Introduction
Depuis la version 2.6.31, perf est intégré au noyau Linux
Il se compose de :
- Back-end perf_events intégré au noyau
- Une application
perf
s’exécutant en espace utilisateur
Le code source de l’application est dans les sources de Linux :
linux/tools/perf
- Documentation sous
linux/tools/perf/Documentation/examples.txt
Il permet d’enregistrer des événements du PMU, mais également des tracepoints du noyau
Fonctionnalités
Perf offre les fonctionnalités suivantes :
- Génération d’arbres d’appel (call graph)
- Collecte d’événements à partir des compteurs hardware disponible dans le PMU
- Collecte de tracepoints du noyau Linux
- Collecte d’événements en temps réel
- Annotation de code source / instructions assembleur
- Une documentation détaillée est disponible sur le wiki officiel
Tracepoints du noyau
Un tracepoint est un appel de fonction placé à un endroit stratégique dans le code du noyau Linux
Perf est capable d’activer les tracepoints :
- Si le tracepoint est désactivé, celui-ci ne fera rien (si ce n’est gaspiller quelques cycles pour tester s’il est activé et utiliser quelques bytes dans l’exécutable)
- S’il est activé, le
tracepoint
notifie celui qui l’a configuré
Les tracepoints permettent de tracer :
- Les appels système
- Les événements TCP/IP
- Les opérations du file system
- Les changements de contexte de l’ordonnanceur
- …
Application utilisateur
L’application perf se décompose en plusieurs sous-commandes
La liste complète peut être obtenue en invoquant perf
sans argument :
perf list
: affiche la liste de tous les événements disponiblesperf stat
: exécute une application et affiche des statistiques des compteurs d’événementsperf top
: outil de profiling en temps réel similaire à la commandetop
, affichant les données des compteurs matérielsperf record
: exécute une commande et enregistre des données de compteur dans un fichier de profiling nomméperf.data
perf report
: lit un fichierperf.data
créé avec la commanderecord
et affiche les informations de profiling
Perf List
> perf list
List of pre-defined events (to be used in -e):
cpu-cycles OR cycles [Hardware event]
instructions [Hardware event]
cache-references [Hardware event]
cache-misses [Hardware event]
branch-instructions OR branches [Hardware event]
branch-misses [Hardware event]
bus-cycles [Hardware event]
stalled-cycles-frontend OR idle-cycles-frontend [Hardware event]
ref-cycles [Hardware event]
cpu-clock [Software event]
task-clock [Software event]
...
Perf Stat
> perf stat ./sudoku-resolver
Performance counter stats for './sudoku-resolver':
17200.968507 task-clock (msec) # 0.999 CPUs utilized
2,019 context-switches # 0.117 K/sec
21 cpu-migrations # 0.001 K/sec
150 page-faults # 0.009 K/sec
66,111,521,094 cycles # 3.843 GHz
13,661,886,259 stalled-cycles-frontend # 20.66% frontend cycles idle
<not supported> stalled-cycles-backend
166,918,528,666 instructions # 2.52 insns per cycle
# 0.08 stalled cycles per insn
12,592,498,548 branches # 732.081 M/sec
368,812,217 branch-misses # 2.93% of all branches
17.222153960 seconds time elapsed
Perf Record et Report
> perf record ./sudoku-resolver
[ perf record: Woken up 11 times to write data ]
[ perf record: Captured and wrote 2.669 MB perf.data (~116626 samples) ]
> perf report
Samples: 69K of event 'cycles', Event count (approx.): 66377473404
84.68% sudoku-resolver sudoku-resolver [.] isAvailable
15.02% sudoku-resolver sudoku-resolver [.] fillSudoku
0.08% sudoku-resolver [i915] [k] gen6_read32
0.05% sudoku-resolver [kernel.kallsyms] [k] _raw_spin_lock_irqsave
Perf Top
> perf top -e cpu-clock
PerfTop: 1579 irqs/sec kernel:99.9% exact: 0.0% [4000Hz cpu-clock], (all, 4 CPUs)
------------------------------------------------------------------------------------
99.73% [kernel] [k] arch_cpu_idle
0.05% [kernel] [k] _raw_spin_unlock_irqrestore
0.04% [kernel] [k] _raw_spin_unlock_irq
0.03% [kernel] [k] tick_nohz_idle_exit
0.01% [kernel] [k] __softirqentry_text_start
0.01% [kernel] [k] copy_page
0.01% [kernel] [k] tcp_write_timer_handler
0.01% [kernel] [k] rcu_idle_exit
0.01% [kernel] [k] __local_bh_enable_ip
0.01% [kernel] [k] preempt_count_sub
0.00% [vdso] [.] __kernel_clock_gettime
0.00% [kernel] [k] put_ctx
0.00% perf [.] 0x000000000008d2ac
0.00% [kernel] [k] __schedule
0.00% [kernel] [k] timespec64_add_safe
0.00% [kernel] [k] el0_svc_common
0.00% libc-2.28.so [.] __vsnprintf_chk
0.00% [kernel] [k] unwind_frame
Résolution des symboles
Perf est capable de donner les informations de performances de manière symbolique, pour ceci il procède de la façon suivante
- Les compteurs hardware donnent l’adresse de l’instruction exécutée
- Perf associe ces adresses aux lignes de code correspondantes
- Les symboles de debug contenus dans l’exécutable sont utilisés
- Il faut donc que notre application soit compilée avec les symboles de debug
(option
-g
du compilateur) - Perf peut également résoudre les symboles au niveau du noyau
Note sur les compteurs
Les compteurs matériels affichés par perf list
sont des compteurs génériques.
Cependant chaque processeur dispose d’une liste de compteurs propre à son architecture.
Perf effectue un mapping entre les compteurs d’une architecture donnée vers ses compteurs génériques.
Par exemple, le compteur cycles est mappé :
- Processeur Intel:
UNHALTED_CORE_CYCLES
(voirarch/x86/kernel/cpu/perf_event.c
) - Processeur AMD:
CPU_CLK_UNHALTED
- Processeur ARM: voir
arch/arm/kernel/perf_event_v7.c
Note sur la précision des événements
Perf est basé sur un échantillonnage par événement event-based sampling
- Cela signifie que seulement une partie des événements (et donc des instructions) sont enregistrés (dès que le compteur génère une interruption)
- On peut configurer l’échantillonnage de deux manières, en spécifiant:
- le nombre d’occurrences d’événements (période) → option
-c
- le nombre de échantillons / secondes (fréquence) → option
-F
- le nombre d’occurrences d’événements (période) → option
- À cause de l’échantillonnage, on peut avoir des cas spéciaux ou notre application
se trouve synchronisée avec la collecte d’événements de
perf
- On aura ainsi des résultats faussés, ce sera toujours la même instruction qui sera enregistrée au moment de l’interruption du compteur.
De plus, le nombre de compteurs est limité par l’architecture
- Si on configure plus d’événements (option
-e
) que de compteurs,perf
fait du multiplexage entre les différents événements.
Plus d’informations sur le wiki de perf