pahole - Analisi del Layout di Struct e Cache-Line Cheatsheet
pahole (“poke-a-hole”) legge informazioni di debug DWARF o BTF e stampa il layout di memoria effettivo delle strutture C — dove si trova ogni campo, quanto padding il compilatore ha inserito e quante cache line la struct attraversa. I compilatori padding le struct per soddisfare l”allineamento, e una struct ordinata incautela può sprecare decine di byte e attraversare cache line extra. Su strutture di dati hot questo si traduce direttamente in cache miss. pahole rende lo spreco visibile in modo da poter riordinare i campi e ridurlo.
Installazione
| Piattaforma | Comando |
|---|
| Debian/Ubuntu | sudo apt install dwarves |
| Fedora/RHEL | sudo dnf install dwarves |
| Arch Linux | sudo pacman -S pahole |
| Dal sorgente | build il progetto dwarves |
| Verifica | pahole --version |
Il tuo binario deve essere costruito con informazioni di debug (-g). I binari privati non hanno nulla da leggere per pahole.
Utilizzo di Base
| Comando | Descrizione |
|---|
pahole ./myprogram | Mostra tutte le struct nel binario |
pahole -C mystruct ./myprogram | Una struct specifica |
pahole -C task_struct /sys/kernel/btf/vmlinux | Struct kernel via BTF |
pahole --sizes ./myprogram | Elenca le dimensioni di struct |
pahole -H 1 ./myprogram | Solo struct con ≥1 buco |
Lettura dell”Output
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 */
};
| Annotazione | Significato |
|---|
/* offset size */ | Offset di byte e dimensione di ogni campo |
XXX N bytes hole | Padding che il compilatore ha inserito |
size: | Dimensione totale di struct |
cachelines: | Quante linee da 64 byte attraversa |
sum holes: | Byte totali sprecati |
last cacheline: | Byte usati nella riga finale |
Ricerca di Spreco in Un Codebase
| Comando | Trova |
|---|
pahole -H 1 ./bin | Struct con buchi |
pahole --nr_members ./bin | Ordinato per numero di membri |
pahole -c 2 ./bin | Struct che attraversano ≥2 cache line |
pahole -E ./bin | Espandi struct nidificate inline |
pahole -a ./bin | Mostra dettagli di allineamento/packing |
# Quali struct sprecano più memoria per padding?
pahole -H 8 ./myprogram | head -50
Fissaggio del Layout
La fix standard è ordinare i campi dal più grande al più piccolo allineamento:
/* Prima: 48 byte, 11 sprecati */
struct bad { char flag; long counter; char name[16]; int id; void *ptr; };
/* Dopo: 40 byte, 0 sprecati */
struct good { long counter; void *ptr; char name[16]; int id; char flag; };
| Tecnica | Effetto |
|---|
| Ordina per allineamento decrescente | Elimina la maggior parte dei buchi |
| Raggruppa campi hot insieme | Mantienili in una cache line |
| Dividi campi freddi in una seconda struct | I dati hot rimangono densi |
__attribute__((packed)) | Rimuove il padding — ma potrebbe rallentare l”accesso non allineato |
| Bitfield | Pacca piccoli flag |
pahole può anche suggerire un riordinamento con --reorganize:
pahole --reorganize -C mystruct ./myprogram
Lavoro su Kernel (BTF)
| Comando | Scopo |
|---|
pahole -C task_struct /sys/kernel/btf/vmlinux | Ispeziona una struct kernel live |
pahole -J vmlinux | Genera BTF da DWARF |
pahole --btf_encode | Codifica BTF per il tooling eBPF |
La generazione di BTF è il motivo per cui dwarves è una dipendenza della build del kernel — CO-RE di eBPF si basa su di essa.
Quando Questo Importa
| Situazione | Impatto |
|---|
| Milioni di istanze di una struct | Il risparmio di memoria scala linearmente |
| Loop hot che tocca i campi di struct | Meno cache line = meno miss |
| Serializzazione di rete/disco | Struct più piccoli, meno I/O |
| Memoria embedded/ristretta | Ogni byte conta |
| Una struct usata due volte | Non disturbarti |
| Tool | Risposte |
|---|
| pahole | Come è disposta questa struct e dove è lo spreco? |
| perf | Sto effettivamente avendo cache miss? |
| valgrind (cachegrind) | Comportamento di cache simulato |
| heaptrack | Dove va la memoria heap? |
Usa perf per confermare che i cache miss sono il tuo collo di bottiglia, poi pahole per fissare il layout che li causa.
Risorse