pahole - Análisis de layout de estructura y línea de cache
pahole (“poke-a-hole”) lee información de debug DWARF o BTF e imprime el layout actual en memoria de estructuras C — dónde se sienta cada campo, cuánto padding insertó el compilador, y cuántas líneas de cache ocupa la estructura. Los compiladores paddean estructuras para satisfacer alineación, y una estructura descuidadamente ordenada puede desperdiciar docenas de bytes y ocupar líneas de cache extra. En estructuras de datos hot eso se traduce directamente a cache misses. pahole hace el desperdicio visible para que puedas reordenar campos y encogerlo.
Instalación
| Plataforma | Comando |
|---|
| Debian/Ubuntu | sudo apt install dwarves |
| Fedora/RHEL | sudo dnf install dwarves |
| Arch Linux | sudo pacman -S pahole |
| Desde source | compilar el proyecto dwarves |
| Verificar | pahole --version |
Tu binario debe ser compilado con info de debug (-g). Binarios stripped no tienen nada para pahole que leer.
Uso básico
| Comando | Descripción |
|---|
pahole ./myprogram | Mostrar todas las estructuras en el binario |
pahole -C mystruct ./myprogram | Una estructura específica |
pahole -C task_struct /sys/kernel/btf/vmlinux | Estructura del kernel vía BTF |
pahole --sizes ./myprogram | Listar tamaños de estructura |
pahole -H 1 ./myprogram | Solo estructuras con ≥1 agujero |
Leyendo la salida
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 */
};
| Anotación | Significado |
|---|
/* offset size */ | Offset y tamaño de bytes de cada campo |
XXX N bytes hole | Padding que insertó el compilador |
size: | Tamaño total de la estructura |
cachelines: | Cuántas líneas de 64 bytes ocupa |
sum holes: | Total de bytes desperdiciados |
last cacheline: | Bytes usados en la línea final |
Encontrando desperdicio en todo un codebase
| Comando | Encuentra |
|---|
pahole -H 1 ./bin | Estructuras con agujeros |
pahole --nr_members ./bin | Ordenadas por conteo de miembros |
pahole -c 2 ./bin | Estructuras que ocupan ≥2 líneas de cache |
pahole -E ./bin | Expandir estructuras anidadas inline |
pahole -a ./bin | Mostrar detalles de alineación/packing |
# ¿Qué estructuras desperdician más memoria en padding?
pahole -H 8 ./myprogram | head -50
Fijando el layout
El fix estándar es ordenar campos de mayor a menor alineación:
/* Antes: 48 bytes, 11 desperdiciados */
struct bad { char flag; long counter; char name[16]; int id; void *ptr; };
/* Después: 40 bytes, 0 desperdiciados */
struct good { long counter; void *ptr; char name[16]; int id; char flag; };
| Técnica | Efecto |
|---|
| Ordenar por alineación descendente | Elimina la mayoría de agujeros |
| Agrupar campos hot juntos | Los mantiene en una línea de cache |
| Split de campos cold en una segunda estructura | Los datos hot permanecen densos |
__attribute__((packed)) | Elimina padding — pero puede ralentizar acceso desalineado |
| Bitfields | Empacar flags pequeños |
pahole incluso puede sugerir un reordenamiento con --reorganize:
pahole --reorganize -C mystruct ./myprogram
Trabajo del kernel (BTF)
| Comando | Propósito |
|---|
pahole -C task_struct /sys/kernel/btf/vmlinux | Inspeccionar una estructura kernel activa |
pahole -J vmlinux | Generar BTF desde DWARF |
pahole --btf_encode | BTF encoding para herramientas eBPF |
La generación de BTF es por qué dwarves es una dependencia de build del kernel — el CO-RE de eBPF depende de ello.
Cuándo importa esto
| Situación | Impacto |
|---|
| Millones de instancias de una estructura | Ahorros de memoria escalan linealmente |
| Loop hot tocando campos de estructura | Menos líneas de cache = menos misses |
| Serialización de red/disco | Estructuras más pequeñas, menos I/O |
| Memoria embebida/restringida | Cada byte cuenta |
| Una estructura usada dos veces | No molestarse |
pahole vs herramientas relacionadas
| Herramienta | Responde |
|---|
| pahole | ¿Cómo se layout esta estructura, y dónde está el desperdicio? |
| perf | ¿Realmente estoy teniendo cache misses? |
| valgrind (cachegrind) | Comportamiento de cache simulado |
| heaptrack | ¿Dónde va la memoria heap? |
Usa perf para confirmar que cache misses es tu cuello de botella, luego pahole para fijar el layout que lo causa.
Recursos