콘텐츠로 이동

pahole - 구조체 레이아웃 및 캐시 라인 분석 치트시트

pahole - 구조체 레이아웃 및 캐시 라인 분석 치트시트

pahole (“poke-a-hole”)은 DWARF 또는 BTF 디버그 정보를 읽고 C 구조체의 실제 메모리 레이아웃을 인쇄합니다 — 각 필드가 앉는 곳, 컴파일러가 삽입한 패딩의 양, 구조체가 걸친 캐시 라인의 개수. 컴파일러는 정렬을 만족시키기 위해 구조체를 패딩하며, 부주의하게 정렬된 구조체는 수십 바이트를 낭비할 수 있고 추가 캐시 라인을 걸칠 수 있습니다. 핫 데이터 구조체에서 이는 직접 캐시 미스로 변환됩니다. pahole은 낭비를 시각화하므로 필드를 재정렬하고 축소할 수 있습니다.

설치

플랫폼명령어
Debian/Ubuntusudo apt install dwarves
Fedora/RHELsudo dnf install dwarves
Arch Linuxsudo pacman -S pahole
소스에서dwarves 프로젝트 빌드
확인pahole --version

바이너리는 디버그 정보로 구축되어야 합니다 (-g). 제거된 바이너리에는 pahole이 읽을 것이 없습니다.

기본 사용법

명령어설명
pahole ./myprogram바이너리의 모든 구조체 표시
pahole -C mystruct ./myprogram하나의 특정 구조체
pahole -C task_struct /sys/kernel/btf/vmlinuxBTF를 통한 커널 구조체
pahole --sizes ./myprogram구조체 크기 나열
pahole -H 1 ./myprogram≥1 구멍이 있는 구조체만

출력 읽기

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 */
};
주석의미
/* offset size */각 필드의 바이트 오프셋 및 크기
XXX N bytes hole컴파일러가 삽입한 패딩
size:총 구조체 크기
cachelines:걸친 64바이트 라인의 개수
sum holes:낭비된 총 바이트
last cacheline:최종 라인에서 사용된 바이트

코드베이스 전체의 낭비 찾기

명령어찾기
pahole -H 1 ./bin구멍이 있는 구조체
pahole --nr_members ./bin멤버 개수로 정렬
pahole -c 2 ./bin≥2 캐시 라인을 걸친 구조체
pahole -E ./bin중첩된 구조체를 인라인으로 확장
pahole -a ./bin정렬/패킹 세부사항 표시
# 어느 구조체가 패딩에 가장 많은 메모리를 낭비하나?
pahole -H 8 ./myprogram | head -50

레이아웃 수정

표준 수정은 큰 것부터 작은 것순으로 필드를 정렬하는 것입니다:

/* 이전: 48 바이트, 11 낭비 */
struct bad  { char flag; long counter; char name[16]; int id; void *ptr; };

/* 이후: 40 바이트, 0 낭비 */
struct good { long counter; void *ptr; char name[16]; int id; char flag; };
기법효과
내림차순 정렬로 정렬대부분의 구멍 제거
핫 필드를 함께 그룹화하나의 캐시 라인에 유지
콜드 필드를 두 번째 구조체로 분할핫 데이터가 조밀하게 유지됨
__attribute__((packed))패딩 제거 — 하지만 정렬되지 않은 접근을 느리게 할 수 있음
Bitfield작은 플래그 압축

pahole은 --reorganize로 재정렬을 제안할 수도 있습니다:

pahole --reorganize -C mystruct ./myprogram

커널 작업 (BTF)

명령어목적
pahole -C task_struct /sys/kernel/btf/vmlinux라이브 커널 구조체 검사
pahole -J vmlinuxDWARF에서 BTF 생성
pahole --btf_encodeeBPF 도구를 위한 BTF 인코딩

BTF 생성이 dwarves가 커널 빌드 종속성인 이유입니다 — eBPF의 CO-RE는 이에 따라 달라집니다.

이것이 중요할 때

상황영향
구조체의 수백만 인스턴스메모리 절약이 선형으로 확장
구조체 필드를 터치하는 핫 루프더 적은 캐시 라인 = 더 적은 미스
네트워크/디스크 직렬화더 작은 구조체, 더 적은 I/O
임베디드/제약 메모리모든 바이트가 중요함
구조체가 두 번 사용됨신경 쓰지 마십시오

pahole vs 관련 도구

도구답변
pahole이 구조체가 어떻게 배치되고, 낭비가 어디에 있나?
perf실제로 캐시를 놓치고 있나?
valgrind (cachegrind)시뮬레이션된 캐시 동작
heaptrack힙 메모리가 어디로 가는가?

perf를 사용하여 캐시 미스가 병목이라는 것을 확인한 후 pahole으로 레이아웃을 수정합니다.

리소스