pahole - Analyse de Disposition de Struct et de Ligne de Cache
pahole (« poke-a-hole ») lit les informations de débogage DWARF ou BTF et imprime la disposition réelle en mémoire des structures C — où chaque champ s’assoit, combien de remplissage le compilateur a inséré, et combien de lignes de cache la struct traversent. Les compilateurs remplissent les structs pour satisfaire l’alignement, et une struct négligemment ordonnée peut gaspiller des dizaines d’octets et traverser des lignes de cache supplémentaires. Sur les structures de données chaudes, cela se traduit directement par des ratés de cache. pahole rend le gaspillage visible pour que vous puissiez réordonner les champs et le réduire.
Installation
| Plateforme | Commande |
|---|
| Debian/Ubuntu | sudo apt install dwarves |
| Fedora/RHEL | sudo dnf install dwarves |
| Arch Linux | sudo pacman -S pahole |
| De source | construire le projet dwarves |
| Vérifier | pahole --version |
Votre binaire doit être construit avec les infos de débogage (-g). Les binaires dépouillés n’ont rien pour pahole à lire.
Utilisation de Base
| Commande | Description |
|---|
pahole ./myprogram | Afficher toutes les structs du binaire |
pahole -C mystruct ./myprogram | Une struct spécifique |
pahole -C task_struct /sys/kernel/btf/vmlinux | Struct du noyau via BTF |
pahole --sizes ./myprogram | Lister les tailles de struct |
pahole -H 1 ./myprogram | Uniquement les structs avec ≥1 trou |
Lecture de la Sortie
struct example {
char flag; /* 0 1 */
/* XXX 7 bytes hole, try to pack */
long int counter; /* 8 8 */
char name[16]; /* 16 16 */
int id; /* 32 4 */
/* XXX 4 bytes hole, try to pack */
void * ptr; /* 40 8 */
/* size: 48, cachelines: 1, members: 5 */
/* sum members: 37, holes: 2, sum holes: 11 */
};
| Annotation | Signification |
|---|
/* offset size */ | Décalage d’octet et taille de chaque champ |
XXX N bytes hole | Remplissage que le compilateur a inséré |
size: | Taille totale de la struct |
cachelines: | Combien de lignes de 64 octets elle traverse |
sum holes: | Total d’octets gaspillés |
last cacheline: | Octets utilisés dans la ligne finale |
Trouver le Gaspillage Partout dans une Base de Code
| Commande | Trouve |
|---|
pahole -H 1 ./bin | Structs avec trous |
pahole --nr_members ./bin | Triées par nombre de membres |
pahole -c 2 ./bin | Structs traversant ≥2 lignes de cache |
pahole -E ./bin | Développer les structs imbriquées en ligne |
pahole -a ./bin | Afficher les détails d’alignement/packing |
# Quelles structs gaspillent le plus de mémoire à cause du remplissage ?
pahole -H 8 ./myprogram | head -50
Fixing Layout
Le correctif standard est ordonnement des champs de l’alignement le plus grand au plus petit :
/* Avant : 48 octets, 11 gaspillés */
struct bad { char flag; long counter; char name[16]; int id; void *ptr; };
/* Après : 40 octets, 0 gaspillé */
struct good { long counter; void *ptr; char name[16]; int id; char flag; };
| Technique | Effet |
|---|
| Ordonnancer par alignement décroissant | Élimine la plupart des trous |
| Grouper les champs chauds | Les garder dans une ligne de cache |
| Diviser les champs froids dans une deuxième struct | Les données chaudes restent denses |
__attribute__((packed)) | Supprime le remplissage — mais peut ralentir l’accès non aligné |
| Bitfields | Empaqueter les petits drapeaux |
pahole peut même suggérer une réorganisation avec --reorganize :
pahole --reorganize -C mystruct ./myprogram
Travail du Noyau (BTF)
| Commande | Objectif |
|---|
pahole -C task_struct /sys/kernel/btf/vmlinux | Inspecter une struct du noyau actif |
pahole -J vmlinux | Générer BTF à partir de DWARF |
pahole --btf_encode | Codage BTF pour les outils eBPF |
La génération de BTF est la raison pour laquelle dwarves est une dépendance de construction du noyau — CO-RE d’eBPF en dépend.
Quand Cela Compte
| Situation | Impact |
|---|
| Des millions d’instances d’une struct | Les économies de mémoire évoluent linéairement |
| Boucle chaude touchant les champs struct | Moins de lignes = moins de ratés |
| Sérialisation réseau/disque | Structs plus petites, moins d’E/S |
| Mémoire embarquée/contrainte | Chaque octet compte |
| Une struct utilisée deux fois | Ne pas se déranger |
pahole vs Outils Associés
| Outil | Réponses |
|---|
| pahole | Comment cette struct est-elle disposée, et où est le gaspillage ? |
| perf | Est-ce que j’ai réellement des ratés de cache ? |
| valgrind (cachegrind) | Comportement simulé du cache |
| heaptrack | Où la mémoire du heap va-t-elle ? |
Utilisez perf pour confirmer que les ratés de cache sont votre goulot d’étranglement, puis pahole pour corriger la disposition qui les cause.
Ressources