TECH 으로 돌아가기
TECH HACKER NEWS 오늘 7분 읽기 27 READS

eBPF 코드의 성능을 재는 법: 파일 오픈 훅으로 본 프로파일링 실전

eBPF 코드의 성능을 재는 법: 파일 오픈 훅으로 본 프로파일링 실전
SOURCE IMAGE · HACKER NEWS

eBPF는 커널을 다시 컴파일하지 않고도 시스템 콜, VFS 계층, 네트워크 경로 등에 안전하게 코드를 붙일 수 있어 관측성과 보안 분야에서 표준 도구로 자리 잡았다. 하지만 커널의 핫 패스에 훅을 하나 얹는다는 것은 곧 그 경로를 지나는 모든 작업에 미세한 비용을 더한다는 뜻이기도 하다. eBPF 워크로드를 운영하거나 직접 eBPF 코드를 작성한다면, 이 비용이 실제로 얼마인지, 그리고 어디에서 발생하는지 측정할 수 있어야 한다. 이 글은 파일 오픈 연산이라는 구체적인 사례를 통해 그 측정 방법 자체를 정리한다.

측정 대상으로 파일 오픈을 고른 이유는 분명하다. 파일 열기는 운영체제에서 가장 빈번하게 호출되는 연산 중 하나이고, 여기에 LSM(Linux Security Module) 훅을 붙여 파일 접근을 감시하는 eBPF 코드는 실무에서 흔하다. 문제는 이런 훅이 붙는 지점이 대개 핫 패스라는 데 있다. 호출 빈도가 높은 경로에서는 한 번의 호출당 몇 나노초를 아끼는 최적화도 시스템 전체 성능에 유의미한 차이를 만든다. 그래서 훅을 붙이기 전과 후를 정량적으로 비교하는 절차가 필요하다.

재현 가능한 벤치마크부터 만든다

프로파일링의 출발점은 잡음이 적은 마이크로벤치마크다. 원문은 의존성을 최소화한 간단한 C 테스트 하네스를 권한다. 핵심 아이디어는 같은 파일을 웜 캐시 상태에서 반복해서 여는 것이다. 이렇게 하면 디스크 I/O나 파일시스템의 변동성 같은 무관한 요인이 걷혀 나가고, 순수하게 오픈 경로의 지연 시간에 집중할 수 있다. 하네스는 libc의 openat() 래퍼 대신 syscall(SYS_openat, …)을 직접 호출해 래퍼 계층의 개입을 배제하고, 처음 10%의 결과는 워밍업 구간으로 간주해 버린다. 파일을 정해진 횟수만큼 연 뒤 각 호출에 걸린 시간을 기록하므로, 이 값을 eBPF 훅 부착 전후로 비교하면 p50/p99 같은 백분위 지표를 뽑을 수 있다.

측정의 안정성을 위해 실행 환경도 통제한다. taskset -c 3으로 프로세스를 CPU 3번에 고정해 코어 간 마이그레이션 잡음을 줄이고, chrt -f 99로 실시간 스케줄링의 최고 우선순위를 부여해 벤치마크가 다른 일반 프로세스에 밀리지 않게 한다. 이렇게 얻은 결과를 파일로 흘려보내 저장하는데, 첫 10%가 버려지므로 예컨대 10만 번을 돌리면 9만 개의 샘플이 남는다. 원문 예시는 /etc/hostname을 대상 파일로 삼는다.

심볼이 보여야 프로파일이 읽힌다

eBPF 코드를 perf로 프로파일링할 때 가장 흔히 막히는 지점은 심볼 해석이다. JIT로 컴파일된 BPF 프로그램의 주소가 이름으로 풀리지 않으면 리포트에 정체불명의 주소만 뜬다. 이를 해결하려면 JIT를 켜고 JIT 컴파일된 BPF 심볼을 노출시키는 설정을 먼저 적용해야 한다. 그러면 perf 리포트가 주소 대신 프로그램 이름을 보여준다. 심볼이 제대로 노출됐는지는 실제 eBPF 코드를 돌린 뒤 rg 같은 도구로 확인하는데, LSM 훅을 재는 경우라면 lsm이라는 문자열이 잡히는지 보면 된다. 참고로 커스텀 커널을 쓰는 환경에서는 perf 바이너리가 표준 경로에 없을 수 있어, 원문 예시처럼 /usr/lib/linux-tools/6.8.0-134-generic/perf 같은 별도 경로를 직접 지정해 줘야 한다.

준비가 끝나면 순서는 두 단계다. 먼저 eBPF 코드를 끈 상태에서 C 하네스로 기준선을 측정해 p50/p99를 계산한다. 그다음 eBPF 코드를 켠 채로 perf record를 돌린다. 이때 -g로 콜 스택을 기록하고 --call-graph fp로 프레임 포인터 기반 언와인딩을 쓰며, 이벤트는 커널 모드의 CPU 사이클만 샘플링하도록 지정한다. 커널 모드에는 시스템 콜, VFS, LSM, eBPF 실행이 포함되고 유저스페이스의 벤치마크 코드는 빠진다. 샘플링 빈도는 997Hz처럼 딱 떨어지지 않는 값을 쓰는데, 이는 주기적인 이벤트와 샘플링이 우연히 정렬돼 왜곡되는 현상을 피하기 위한 실전 팁이다.

병목이 보이면 최적화가 시작된다

수집한 perf.data는 정렬해 텍스트로 뽑거나 Inferno 같은 도구로 플레임그래프로 시각화한다. 파일 오픈 LSM 훅을 재는 사례에서 관심 대상은 bpf_lsm_file_open과 그 위로 쌓인 스택, 특히 여기서 이어지는 테일 콜들이다. 원문의 예시 출력은 바로 이 지점, 즉 bpf_lsm_file_open과 그 테일 콜에서 시간이 소비되고 있음을 보여준다. 이곳이 핫 패스라는 사실이 확인되면, 할당 하나를 줄이거나 CPU 사이클 몇 개를 아끼는 작업이 시스템 전체에 큰 영향을 준다는 결론으로 이어진다.

다만 이 글은 의도적으로 구체적인 수치를 제시하지 않는다. 오버헤드의 크기는 훅이 실제로 무슨 일을 하느냐에 따라 크게 달라지기 때문에, 남의 벤치마크 숫자를 그대로 가져다 쓰는 것은 의미가 없다는 입장이다. 대신 자신의 환경에서 직접 숫자를 뽑는 방법을 익히는 편이 실무적으로 훨씬 유용하다. 최적화의 방향도 프로파일 결과가 알려준다. 무언가를 캐싱하는 단순한 조치일 수도 있고, 문제가 드러난 지점에 맞춰 더 나은 알고리즘을 고안하는 일일 수도 있다. 결국 C 하네스가 주는 p50/p99라는 정량 지표와 perf가 짚어주는 병목 위치를 함께 놓고 보면, eBPF 코드가 시스템에 미치는 성능 영향을 명확히 판단하고 어디를 손봐야 할지 겨냥할 수 있다.

SOURCE · HACKER NEWS
원문 전체 보기 → https://naveensrinivasan.com/posts/2026-07-22-how-do-i-profi...
SHARE
처리 중...