eBPF·bpftrace 동적 트레이싱 — 커널 무수정 관측
#한 줄 요약
“eBPF는 검증된 작은 프로그램을 커널 안에서 실행해, 안전하면서도 ftrace보다 표현력 높은 분석을 가능하게 합니다.”
#어떤 문제를 푸는가
ftrace는 강력하지만 데이터를 사용자 공간으로 모두 내보낸 뒤 후처리하는 구조입니다. 100 KHz syscall stream을 그대로 dump하면 디스크가 금방 차고 분석도 어렵습니다.
eBPF는 검증된 BPF bytecode를 커널 hook 지점에서 직접 실행하므로, hash map에 집계하거나 histogram으로 압축한 결과만 사용자 공간으로 가져옵니다. 측정 overhead가 낮고, 코드 한 줄로 “프로세스별 read 시스템 호출 횟수”를 집계할 수 있습니다.
bpftrace는 awk와 비슷한 DSL로 eBPF를 손쉽게 작성하는 도구이며, BCC는 Python으로 더 복잡한 분석기를 만드는 framework입니다. 이 글에서는 두 도구와 그 기반 mechanism을 다룹니다.
#BPF VM과 Verifier
eBPF 프로그램은 64-bit register 10개의 가상 머신에서 실행됩니다. 커널이 bytecode를 로드할 때 verifier가 다음을 검사합니다.
- 모든 분기가 유한 시간 안에 종료되는가- 모든 메모리 접근이 유효한 범위 안인가- Loop은 bounded인가 (5.3+ bounded loop 허용)- 사용 가능한 helper function만 호출하는가검증을 통과한 BPF는 JIT 컴파일되어 native 속도로 실행됩니다. 따라서 잘못 짠 BPF는 시스템을 죽이지 않고 로드 자체가 실패합니다.
uname -r # 4.9+ 권장, 5.x 이상 활용도 ↑zcat /proc/config.gz | grep BPF # CONFIG_BPF=y 확인#bpftrace One-liner
설치는 대부분 distro에서 패키지로 가능합니다.
apt install bpftrace자주 쓰는 one-liner부터 살펴봅니다.
# 시스템 전체 syscall 빈도bpftrace -e 'tracepoint:raw_syscalls:sys_enter { @[comm] = count(); }'
# 프로세스별 read 호출 횟수bpftrace -e 'tracepoint:syscalls:sys_enter_read { @[comm] = count(); }'
# read latency 분포 (histogram)bpftrace -e ' tracepoint:syscalls:sys_enter_read { @start[tid] = nsecs; } tracepoint:syscalls:sys_exit_read /@start[tid]/ { @us = hist((nsecs - @start[tid]) / 1000); delete(@start[tid]); }'@는 BPF map을 의미하며, 출력은 종료 시점에 자동으로 표시됩니다.
@us:[1] 12 | |[2, 4) 234 |@@@ |[4, 8) 1024 |@@@@@@@@@@@@@@ |[8, 16) 3456 |@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@|[16, 32) 1200 |@@@@@@@@@@@@@@@@@@ |[32, 64) 456 |@@@@@@ |hist()는 log2 buckets, lhist()는 linear buckets를 생성합니다.
#kprobe·uprobe·tracepoint·USDT 비교
| 종류 | 위치 | 안정성 | 비용 |
|---|---|---|---|
| Tracepoint | 커널 정적 probe | 안정 | 낮음 |
| Kprobe | 커널 임의 함수 | 불안정 | 중간 |
| Uprobe | 사용자 함수 | 사용자 ABI 의존 | 중간-높음 |
| USDT | 사용자 정적 probe | 안정 | 낮음 |
Tracepoint는 커널이 보장하는 API이므로 버전이 바뀌어도 잘 동작합니다. Kprobe는 임의 함수에 hook을 걸 수 있지만 함수 이름이 바뀌면 깨집니다.
# kprobe — 임의 커널 함수bpftrace -e 'kprobe:vfs_read { @[comm] = count(); }'
# uprobe — 사용자 함수bpftrace -e 'uprobe:/lib/x86_64-linux-gnu/libc.so.6:malloc { @bytes = hist(arg0);}'
# USDT — 사용자 정적 probebpftrace -e 'usdt:/usr/sbin/mysqld:mysql:query__start { @ = count(); }'USDT는 application이 DTRACE_PROBE 매크로로 미리 정의해 둔 probe입니다. MySQL, PostgreSQL, OpenJDK, libpython 등이 제공합니다.
#BCC — Python으로 복잡한 분석
BCC(BPF Compiler Collection)는 C로 BPF를 작성하고 Python으로 결과를 처리하는 framework입니다. 즉시 쓰는 도구가 풍부합니다.
apt install bpfcc-tools
opensnoop-bpfcc # 열린 파일 실시간execsnoop-bpfcc # exec 호출 실시간biolatency-bpfcc # block I/O latency histogramrunqlat-bpfcc # run queue latencytcpconnect-bpfcc # TCP connect 호출profile-bpfcc -F 99 -ag 30 # 99 Hz CPU profileprofile-bpfcc는 stack collapsed 형식으로 출력하므로 flamegraph로 바로 그릴 수 있습니다.
profile-bpfcc -F 99 -af 30 > out.stacksflamegraph.pl < out.stacks > flame.svg#perf vs eBPF — Overhead 비교
도구 Overhead 수집 데이터perf record -F 4000 3-5% sample stackftrace function 10-30% 전 함수 진입ftrace tracepoint 1-5% 선택 eventbpftrace tracepoint 0.5-2% 집계된 결과bpftrace kprobe 1-3% 집계된 결과BCC profile 1-2% sample stackeBPF의 핵심 이득은 raw event를 dump하지 않고 커널 안에서 집계하는 점입니다. 100만 event를 1000 bucket histogram으로 압축하면 사용자 공간으로 가는 데이터는 수 KB로 끝납니다.
#시나리오 — 갑작스런 latency spike 진단
# 1. run queue latency 확인runqlat-bpfcc 10 1
# 2. CPU에서 가장 시간을 쓰는 함수profile-bpfcc -F 99 -af 30 > out.stacksflamegraph.pl < out.stacks > flame.svg
# 3. block I/O 의심되면biolatency-bpfcc
# 4. 특정 syscall이 의심되면bpftrace -e ' tracepoint:syscalls:sys_enter_read { @start[tid] = nsecs; } tracepoint:syscalls:sys_exit_read /@start[tid]/ { $dur = nsecs - @start[tid]; if ($dur > 10000000) { printf("%s pid=%d dur=%dms\n", comm, pid, $dur/1000000); } delete(@start[tid]); }'이 흐름으로 30초 안에 hot path와 latency outlier를 분리할 수 있습니다.
#BPF_LSM과 보안 측면
5.7+ 커널은 BPF_LSM hook을 지원합니다. 보안 정책을 BPF로 작성해 LSM(Linux Security Module) hook에 attach할 수 있으며, SELinux 같은 정적 정책보다 유연합니다.
SEC("lsm/bprm_check_security")int BPF_PROG(bprm_check_security, struct linux_binprm *bprm) { /* exec 차단 정책 */ return -EPERM;}Cilium Tetragon이 이 방향의 대표적 활용이며, 5-10편에서 다룹니다.
#자주 보는 함정과 안티패턴
⚠️ Bounded loop가 없는 커널에서 loop 사용
for (int i = 0; i < n; i++) { ... } // verifier reject5.3 이전에는 unrolled loop만 가능했습니다. #pragma unroll이나 bounded loop를 사용해야 합니다.
⚠️ Stack 크기 초과
BPF stack은 512 byte 제한큰 struct를 stack에 두면 verifier reject큰 데이터는 BPF map이나 per-CPU array를 사용해야 합니다.
⚠️ Uprobe ABI 의존
uprobe:/lib/libc.so.6:malloclibc 업그레이드로 symbol이 사라지거나 inline되면 즉시 깨집니다. USDT가 더 안정적입니다.
⚠️ map 정리 누락
@start[tid] = nsecs;# 끝날 때 delete(@start[tid]) 없음 → memory leak특히 process exit으로 sys_exit가 호출되지 않는 경우 map entry가 누적됩니다.
#정리
- eBPF는 검증된 BPF bytecode를 커널 hook에서 JIT 실행하는 framework입니다.
- bpftrace는 awk 같은 DSL로 one-liner부터 복잡한 분석까지 작성 가능합니다.
- BCC는 Python framework이며 opensnoop, biolatency, runqlat 등 즉시 쓰는 도구를 제공합니다.
- Tracepoint와 USDT는 안정적이며, kprobe와 uprobe는 강력하지만 ABI에 의존합니다.
- 커널 안에서 hash map으로 집계하므로 raw event dump보다 overhead가 훨씬 낮습니다.
- BPF_LSM으로 보안 hook까지 확장 가능합니다.
다음 편은 Flamegraph 분석 — sampling 결과를 한 장의 그림으로.
#관련 항목
Embedded Performance Engineering · 44 of 57
- 1Embedded Performance Engineering — 임베디드 성능 엔지니어링 시리즈 소개
- 2임베디드 성능 분석 방법론 — Measure → Analyze → Optimize 사이클
- 3성능 지표 정의 — Latency·Throughput·Utilization 분석
- 4성능 측정의 기본 — Wall-Clock·CPU Cycle·Instruction Count
- 5성능 데이터 통계적 분석 — Percentile·Histogram·평균의 함정
- 6실시간 성능 분석 — WCET·Jitter·Deadline Miss 측정
- 7임베디드 벤치마킹 기초 — 재현성·Warmup·노이즈 제거
- 8성능 모델링 — Amdahl·Gustafson·Roofline Model 적용
- 9프로파일링 기법 개요 — Sampling vs Instrumentation·PGO·LTO
- 10CPU 파이프라인 분석 — 5-stage·Cortex-M·Cortex-A 비교
- 11Pipeline Stall 분석 — Data·Structural·Control Hazard·Forwarding
- 12Branch Prediction 분석 — Static·2-bit·BTB·BHT·Mispredict 비용
- 13Speculative Execution 분석 — OoO·Reorder Buffer·Register Renaming
- 14CPU Cache 기초 — L1·L2·L3·Set Associative·Replacement Policy
- 15Cache Miss 3C Model 분석 — Compulsory·Capacity·Conflict
- 16Cache Line 최적화 — Alignment·Prefetch·False Sharing 처리
- 17메모리 대역폭 분석 — STREAM·Roofline·Bus Saturation 측정
- 18SIMD·NEON 활용 — 128-bit Vector·Auto-Vectorization·SVE/SVE2
- 19PMU·HPM 하드웨어 카운터 분석 — 정밀 성능 진단
- 20임베디드 Bus Architecture — AHB·AXI·CHI 진화와 5-Channel
- 21Bus Contention 진단 — Arbitration·QoS·Starvation 측정
- 22DMA 성능 최적화 — Burst·Scatter-Gather·Chain·Cache 일관성
- 23DMA vs CPU Copy 성능 비교 — Break-even·Setup Overhead 실측
- 24Interrupt Latency 분석 — 진입·종료·Tail-Chaining·Late Arrival
- 25Interrupt Storm 처리 — NAPI·Rate-Limit·Polling 전환
- 26MMIO 접근 성능 — Cache Policy·Write-Combining·Volatile·Barrier
- 27Peripheral Clock 분석 — PLL·Divider·Gating·DVFS
- 28Power vs Performance 트레이드오프 — DVFS·Race-to-Idle·Big.LITTLE
- 29Thermal Throttling 분석 — Junction Temp·Trip Point·냉각
- 30CXL Interconnect 분석 — AI 시대 메모리 대역폭 확장
- 31Concurrency 기초 — Concurrency vs Parallelism·Race·Memory Model
- 32False Sharing 진단 — Cache Line Ping-Pong·Padding·측정
- 33Lock Contention 분석 — Wait·Hold·Convoy·측정 기법
- 34Spinlock 성능 분석 — Spin-Wait vs Context Switch·Ticket·MCS
- 35Mutex 성능 분석 — Futex·Adaptive·Priority Inheritance
- 36Reader-Writer Lock 성능 — Reader/Writer Priority·RCU·Seqlock
- 37Lock-Free 자료구조 성능 — CAS·ABA·Hazard Pointer·Epoch Reclamation
- 38Memory Ordering 분석 — Acquire·Release·Seq-Cst·ARM Relaxed Model
- 39Cache Coherency 프로토콜 — MESI·MOESI·Snoop·Directory
- 40SMP 성능 분석 — Per-Core·Affinity·Load Balance·Scalability
- 41Linux perf 기초 — stat·record·report 활용
- 42Linux perf 고급 — Raw Event·Tracepoint·perf script
- 43ftrace 활용 — function·function_graph·latency tracer
- 44eBPF·bpftrace 동적 트레이싱 — 커널 무수정 관측
- 45Flamegraph 분석 — On-CPU·Off-CPU·Differential
- 46ARM DS·Lauterbach 분석 — Hardware Trace 전문 도구
- 47Bare-metal 프로파일링 — GPIO·DWT·SysTick·ITM 활용
- 48NVIDIA Nsight Systems — GPU·NPU 포함 시스템 분석
- 49모던 프로파일러 비교 — Tracy·Hotspot·uftrace·Coz
- 50연속 프로파일링 — Parca·Pixie·Pyroscope·Tetragon
- 51실전 사례 — ISR Latency 100µs Deadline Miss 추적
- 52실전 사례 — Matrix Multiply가 예상의 10배 느린 이유
- 53실전 사례 — 8-core가 4-core를 넘으면 throughput이 떨어지는 이유
- 54실전 사례 — 카메라 1080p 60fps가 30fps로 떨어지는 이유
- 55CXL.mem 지연·대역폭 실측 — Direct·Switch·Pooled 토폴로지 비교
- 56CXL 성능 프로파일링 도구 — cxl-cli·DAMON·perf-mem 활용
- 57실전 사례 — CXL.mem 추가로 LLM inference KV cache 처리량 회복
관련 글
연속 프로파일링 — Parca·Pixie·Pyroscope·Tetragon
eBPF 기반 continuous profiling. Parca, Pixie, Pyroscope, Cilium Tetragon으로 24/7 분석.
실전 사례 — CXL.mem 추가로 LLM inference KV cache 처리량 회복
70B 모델 KV cache가 HBM 한계를 넘어 throughput이 무너졌을 때, CXL.mem 256 GB pool 추가로 회복한 실전 케이스.
CXL 성능 프로파일링 도구 — cxl-cli·DAMON·perf-mem 활용
CXL.mem 환경 성능 도구 — cxl-cli 토폴로지·DAMON page activity·perf-mem로 보는 CXL 트래픽·numastat 통계.
이 글을 참조하는 글 (5)
- CXL 성능 프로파일링 도구 — cxl-cli·DAMON·perf-mem 활용— Embedded Performance Engineering
- 연속 프로파일링 — Parca·Pixie·Pyroscope·Tetragon— Embedded Performance Engineering
- Flamegraph 분석 — On-CPU·Off-CPU·Differential— Embedded Performance Engineering
- ftrace 활용 — function·function_graph·latency tracer— Embedded Performance Engineering
- epoll 실전 — LT·ET·ONESHOT·EXCLUSIVE 비교— Modern Embedded Recipes