eBPF 프로그램은 Linux Kernel 내부에서 다양한 이벤트를 수집할 수 있습니다. 하지만 커널에서 생성된 데이터를 사용자 공간(User Space)의 프로그램으로 안전하고 빠르게 전달하는 메커니즘이 필요합니다.
초기 eBPF 환경에서는 Perf Buffer(Perf Event Buffer) 가 표준적인 데이터 전달 방식으로 사용되었습니다. Perf Buffer는 Linux의 Performance Monitoring Infrastructure를 기반으로 만들어졌으며, 오랫동안 BCC와 bpftrace 같은 도구에서 기본 데이터 전달 방식으로 활용되었습니다.
최근에는 Ring Buffer가 등장하면서 많은 신규 프로젝트가 Ring Buffer를 사용하고 있지만, Perf Buffer는 여전히 수많은 운영 환경과 기존 프로젝트에서 중요한 역할을 수행하고 있습니다.
이번 글에서는 Perf Buffer의 개념과 구조, 동작 원리, 주요 API, Ring Buffer와의 차이점, 실무 활용 사례를 자세히 알아보겠습니다.
Linux Perf Buffer란?
Perf Buffer는 eBPF 프로그램이 생성한 이벤트를 사용자 공간으로 전달하기 위한 이벤트 버퍼(Event Buffer) 입니다.
기본 구조는 다음과 같습니다.
eBPF Program
↓
Perf Event Buffer
↓
Kernel
↓
User Space
↓
Application
Kernel은 Perf Event Buffer에 이벤트를 저장하고, User Space 프로그램은 이를 읽어 처리합니다.
Perf Buffer가 필요한 이유
예를 들어 다음과 같은 정보를 실시간으로 수집한다고 가정해 보겠습니다.
- 프로세스 실행
- 시스템 콜 호출
- 파일 접근
- 네트워크 연결
- 디스크 I/O
이러한 이벤트를 사용자 프로그램으로 전달하지 못하면 실시간 분석이나 모니터링이 불가능합니다.
Perf Buffer는 이러한 문제를 해결하기 위해 설계되었습니다.
Perf Buffer의 동작 원리
전체 흐름은 다음과 같습니다.
Kernel Event
↓
eBPF Program
↓
bpf_perf_event_output()
↓
Perf Event Buffer
↓
poll()
↓
User Program
커널에서 생성된 이벤트가 Perf Buffer를 거쳐 사용자 공간으로 전달됩니다.
Perf Buffer 구조
Perf Buffer는 CPU별로 독립적인 버퍼를 생성합니다.
CPU0
↓
Perf Buffer 0
↓
User Thread
-------------------
CPU1
↓
Perf Buffer 1
↓
User Thread
각 CPU가 자신의 버퍼를 사용하므로 동시성이 뛰어납니다.
Perf Buffer의 특징
대표적인 특징은 다음과 같습니다.
- CPU별 버퍼 사용
- 높은 성능
- 오래된 Kernel 지원
- BCC 기본 방식
- bpftrace 지원
- Perf Event 기반
Linux 4.x 환경에서도 널리 사용됩니다.
Perf Buffer Map 생성
eBPF 프로그램에서는 다음과 같이 정의합니다.
struct {
__uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY);
} events SEC(".maps");
Perf Event Array 타입을 사용합니다.
이벤트 출력
eBPF 프로그램에서 이벤트를 전송할 때는 다음 API를 사용합니다.
bpf_perf_event_output(ctx,
&events,
BPF_F_CURRENT_CPU,
&event,
sizeof(event));
현재 CPU의 Perf Buffer에 이벤트를 기록합니다.
User Space에서 읽기
libbpf에서는 Perf Buffer 객체를 생성합니다.
perf_buffer__new()
이후 Poll을 수행합니다.
perf_buffer__poll()
새로운 이벤트가 발생하면 Callback 함수가 자동으로 실행됩니다.
Perf Buffer API
대표적으로 사용하는 API는 다음과 같습니다.
| API | 설명 |
|---|---|
| perf_buffer__new() | Perf Buffer 생성 |
| perf_buffer__poll() | 이벤트 수신 |
| perf_buffer__free() | 메모리 해제 |
| bpf_perf_event_output() | 이벤트 출력 |
현재도 많은 프로젝트에서 사용되고 있습니다.
Perf Buffer와 Ring Buffer의 차이
| 항목 | Perf Buffer | Ring Buffer |
|---|---|---|
| 도입 시기 | 초기 eBPF | Linux 5.8 |
| 버퍼 구조 | CPU별 버퍼 | 공유 버퍼 |
| 이벤트 순서 | CPU별 유지 | 전체 순서 유지 |
| 메모리 사용 | 비교적 많음 | 효율적 |
| 처리량 | 우수 | 매우 우수 |
| 최신 프로젝트 | 감소 추세 | 권장 |
Ring Buffer가 성능 면에서 우수하지만 Perf Buffer도 여전히 많이 사용됩니다.
Perf Buffer의 장점
Perf Buffer는 다음과 같은 장점을 제공합니다.
- 오래된 Kernel과 높은 호환성
- 안정적인 동작
- 다양한 기존 도구 지원
- CPU별 병렬 처리
- BCC와 뛰어난 호환성
특히 레거시 환경에서는 여전히 중요한 역할을 합니다.
Perf Buffer의 단점
반면 다음과 같은 한계도 있습니다.
- CPU마다 버퍼를 관리해야 함
- 이벤트 순서가 CPU별로 나뉨
- 메모리 사용량 증가
- Ring Buffer보다 구현 복잡
이러한 이유로 최신 프로젝트는 Ring Buffer를 선호합니다.
실무에서 자주 사용하는 명령어
Kernel 버전 확인
uname -r
Perf Event 지원 확인
sudo bpftool feature
Program 확인
sudo bpftool prog show
Map 확인
sudo bpftool map show
BCC 설치 확인
which execsnoop
bpftrace 설치 확인
bpftrace --version
Perf Buffer를 사용하는 대표 도구
대표적인 도구는 다음과 같습니다.
| 도구 | Perf Buffer 사용 |
|---|---|
| BCC | O |
| bpftrace | O |
| execsnoop | O |
| opensnoop | O |
| biosnoop | O |
| tcpconnect | O |
많은 기존 eBPF 도구가 Perf Buffer를 기반으로 구현되어 있습니다.
실무 사례
예를 들어 Linux 4.19 기반의 운영 서버에서 성능 문제를 분석해야 한다고 가정해 보겠습니다.
Ring Buffer는 사용할 수 없기 때문에 다음과 같은 절차를 사용합니다.
- BCC 도구 실행
- eBPF 프로그램 로드
- Perf Buffer 생성
- 시스템 콜 이벤트 기록
- User Space에서 Poll 수행
- 실시간 분석 및 로그 저장
이처럼 오래된 커널 환경에서는 Perf Buffer가 여전히 가장 현실적인 선택입니다.
자주 묻는 질문
Perf Buffer와 Ring Buffer 중 어떤 것을 사용해야 하나요?
Linux 5.8 이상에서 새로운 eBPF 프로젝트를 개발한다면 Ring Buffer를 사용하는 것이 일반적으로 권장됩니다. 반면 오래된 커널을 지원해야 하거나 기존 BCC 기반 프로젝트를 유지해야 한다면 Perf Buffer가 적합합니다.
Perf Buffer는 더 이상 사용되지 않나요?
아닙니다. Ring Buffer가 등장하면서 신규 프로젝트에서는 사용 비중이 줄었지만, BCC와 다양한 운영 환경에서는 지금도 널리 활용되고 있습니다.
Perf Buffer는 CPU마다 버퍼를 사용하는 이유가 무엇인가요?
CPU별 버퍼를 사용하면 여러 CPU가 동시에 이벤트를 기록할 때 경쟁을 줄일 수 있어 병렬 처리 성능을 높일 수 있습니다. 다만 CPU 간 이벤트 순서를 맞추기 어렵다는 단점도 있습니다.
마무리
Linux Perf Buffer는 eBPF 프로그램과 사용자 공간 사이에서 이벤트를 전달하는 대표적인 메커니즘입니다. CPU별 버퍼 구조를 기반으로 높은 성능을 제공하며, BCC와 bpftrace 같은 기존 도구에서 오랫동안 활용되어 왔습니다. 최신 환경에서는 Ring Buffer가 점차 표준으로 자리 잡고 있지만, Perf Buffer는 레거시 시스템과 기존 프로젝트를 이해하기 위해 여전히 중요한 기술입니다.