Linux 성능 병목을 추적하는 perf·vmstat·iostat·strace·ltrace
perf, vmstat, iostat, strace, ltrace로 CPU·메모리·디스크 I/O·시스템 콜 병목을 진단하는 Linux 성능 분석 방법
2026-08-14 · 최초 발행 2026-01-19
병목이 보이지 않을 때 먼저 나눠 볼 계층
성능 저하는 CPU, 메모리, 디스크, 네트워크처럼 서로 다른 계층에서 생긴다. 한 지표만 보고 원인을 단정하면 엉뚱한 곳을 최적화하기 쉽다. Linux의 perf, vmstat, iostat, strace, ltrace는 각각 다른 관측 지점을 제공하며, 함께 사용하면 시스템 상태부터 코드와 호출 경로까지 추적할 수 있다.
perf로 CPU 이벤트와 실행 경로 읽기
perf는 perf_event_open() 시스템 콜을 통해 커널 perf 코어와 연결되고, PMU·소프트웨어 이벤트·트레이스포인트에서 데이터를 수집한다.
perf stat은 기본 성능 통계를 모으고, perf record는 샘플을 저장한다. 저장한 결과는 perf report로 분석할 수 있다. 실시간 상태는 perf top, 시스템 콜 추적은 perf trace, 어셈블리 수준 확인은 perf annotate가 담당한다.
실행 단위의 통계 수집
# 기본 통계 수집
perf stat ./my_program
# 상세 통계 (더 많은 이벤트)
perf stat -d ./my_program
# 특정 이벤트만 측정
perf stat -e cycles,instructions,cache-misses,branch-misses ./my_program
# 실행 중인 프로세스 모니터링 (10초간)
perf stat -p <PID> -d sleep 10
# CPU별 통계
perf stat -a -A sleep 5
샘플을 남기고 호출 그래프 확인하기
# CPU 샘플링 (기본 주파수: 1000Hz)
perf record -g ./my_program
# 높은 주파수로 샘플링
perf record -F 4000 -g ./my_program
# 특정 CPU에서만 샘플링
perf record -C 0,1 -g ./my_program
# 커널 함수 포함
perf record -g --all-kernel ./my_program
# 분석 결과 출력
perf report --stdio
perf report -g graph,0.5,caller
# Call-graph 생성 (flame graph)
perf script | stackcollapse-perf.pl | flamegraph.pl > flame.svg
PMU 이벤트를 직접 지정하면 캐시, 분기 예측, TLB처럼 관심 있는 하드웨어 동작을 좁혀 볼 수 있다.
# 사용 가능한 이벤트 목록
perf list
# 캐시 관련 상세 분석
perf stat -e L1-dcache-loads,L1-dcache-load-misses,LLC-loads,LLC-load-misses ./my_program
# 분기 예측 분석
perf stat -e branches,branch-misses ./my_program
# TLB 미스 분석
perf stat -e dTLB-loads,dTLB-load-misses,iTLB-loads,iTLB-load-misses ./my_program
vmstat에서 CPU 대기와 메모리 압박 가르기
vmstat은 프로세스 상태, 메모리, 스왑, I/O, 시스템, CPU 지표를 한 화면에서 확인하게 해 준다. 전반적인 상태를 먼저 훑을 때 유용하다.
# 기본 사용법 (1초 간격, 10회)
vmstat 1 10
# 출력 예시:
# procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
# r b swpd free buff cache si so bi bo in cs us sy id wa st
# 2 0 0 2048576 204800 4096000 0 0 5 10 500 1000 25 10 60 5 0
r 값이 높으면 CPU 경합과 더 많은 CPU 코어의 필요성을 검토할 수 있다. b 값이 높다면 I/O 대기와 디스크 성능을 살핀다. si/so > 0은 스왑 발생과 메모리 부족 상태를 뜻하며, wa 증가는 I/O 대기와 디스크 병목의 신호다. cs가 높을 때는 과도한 컨텍스트 스위칭과 스레드 수를 점검한다.
# 메모리 상세 정보
vmstat -s
# 디스크 통계
vmstat -d
# 파티션별 통계
vmstat -p /dev/sda1
# 슬랩 캐시 정보
vmstat -m
# 이벤트 카운터 및 메모리 통계
vmstat -a 1 5
iostat으로 디스크 대기 시간을 확인하기
디스크 I/O가 의심되면 iostat의 확장 통계로 디바이스별 요청량, 대기 시간, 사용률을 확인한다.
# 기본 출력
iostat
# 확장 통계 (1초 간격, 5회)
iostat -x 1 5
# 특정 디바이스만
iostat -x sda 1
# MB 단위 출력
iostat -x -m 1 5
# CPU와 디스크 통계 모두 출력
iostat -xc 1 5
# 출력 예시 해석:
# Device r/s w/s rkB/s wkB/s rrqm/s wrqm/s %util await svctm
# sda 100.0 50.0 4096.0 2048.0 5.0 10.0 85.0 12.5 8.5
r/s, w/s는 초당 읽기와 쓰기 요청 수다. rkB/s, wkB/s는 초당 읽기와 쓰기 데이터량(KB)을 나타낸다. await는 평균 I/O 대기 시간(ms), svctm은 평균 서비스 시간(ms)이며, %util은 디바이스 사용률이다. %util이 100%에 가까우면 포화 상태를 의심한다.
# 파티션별 통계
iostat -p sda 1
# NFS 통계 포함
iostat -n 1
# 디바이스 그룹별 출력
iostat -g total sda sdb sdc 1
# JSON 형식 출력 (스크립트 처리용)
iostat -o JSON 1 5
strace로 시스템 콜 비용을 추적하기
strace는 프로그램의 시스템 콜을 추적한다. 실행 중인 프로세스에 연결하거나, 호출 유형을 필터링하고, 통계 및 타임스탬프를 기록할 수 있다.
# 프로그램 실행 추적
strace ./my_program
# 실행 중인 프로세스에 연결
strace -p <PID>
# 시스템 콜 통계
strace -c ./my_program
# 타임스탬프 포함
strace -t ./my_program
strace -tt ./my_program # 마이크로초 단위
strace -ttt ./my_program # epoch 시간
# 출력을 파일로 저장
strace -o trace.log ./my_program
파일, 네트워크, 시그널처럼 관심 있는 시스템 콜 영역만 남기면 추적 결과를 줄일 수 있다.
# 파일 관련 시스템 콜만
strace -e trace=file ./my_program
# 네트워크 관련 시스템 콜만
strace -e trace=network ./my_program
# open 계열 시스템 콜만
strace -e trace=open,openat ./my_program
# read/write 추적
strace -e trace=read,write -e read=0,1,2 -e write=0,1,2 ./my_program
# 시그널 추적
strace -e trace=signal ./my_program
프로세스가 자식 프로세스나 여러 스레드를 만들면 추적 범위도 함께 넓혀야 한다.
# 자식 프로세스 추적
strace -f ./my_program
# 스레드 ID 출력
strace -f -ff -o trace ./my_program
# 각 스레드의 출력을 별도 파일로 (trace.PID 형식)
strace -ff -o trace ./my_program
호출 횟수와 시간으로 정렬하거나, 지연된 호출만 걸러 파일 접근 패턴을 확인할 수 있다.
# 시스템 콜별 시간 측정
strace -c -S calls ./my_program
# 느린 시스템 콜 찾기 (100ms 이상만)
strace -T -e trace=all -w ./my_program 2>&1 | awk '/<[0-9]+\.[1-9]/{print}'
# 파일 접근 패턴 분석
strace -e trace=open,read,write,close -o file_access.log ./my_program
grep -E 'open|read|write|close' file_access.log
ltrace로 라이브러리 호출을 따라가기
ltrace는 라이브러리 함수 호출을 관찰한다. 시스템 콜보다 상위의 호출 경로를 확인하거나, 특정 라이브러리와 함수에 관심을 둘 때 사용할 수 있다.
# 라이브러리 함수 호출 추적
ltrace ./my_program
# 실행 중인 프로세스에 연결
ltrace -p <PID>
# 함수 호출 통계
ltrace -c ./my_program
# 시스템 콜도 함께 추적
ltrace -S ./my_program
# 출력을 파일로 저장
ltrace -o ltrace.log ./my_program
# 특정 라이브러리만 추적
ltrace -l libpthread.so.0 ./my_program
# 특정 함수만 추적
ltrace -e malloc+free ./my_program
ltrace -e 'malloc*' ./my_program # malloc, malloc_usable_size 등
# 함수 인자 상세 출력
ltrace -A 100 ./my_program # 배열 인자 100개까지 출력
메모리 할당과 해제 호출을 추적하면 누수 여부를 조사하는 단서가 된다.
# malloc/free 추적
ltrace -e malloc+free+realloc ./my_program
# 통계로 확인
ltrace -c -e malloc+free ./my_program
# 각 호출의 스택 트레이스 (GDB와 함께)
ltrace -w 3 -e malloc ./my_program
관측 범위를 좁혀 가는 진단 흐름
전반적인 상태를 vmstat으로 확인한 뒤 CPU, I/O, 메모리 부족 여부에 따라 다음 도구를 고른다. CPU 병목은 perf top 또는 perf record로 핫스팟을 찾고, 이후 perf annotate로 코드 최적화 대상을 확인한다. I/O 병목은 iostat과 I/O 패턴·캐싱 개선으로 이어지며, 메모리 부족은 vmstat -s, free -h, 메모리 누수 확인으로 이어진다. 어느 쪽에도 명확히 속하지 않으면 strace와 ltrace로 호출을 추적한다.
다음 스크립트는 시스템 상태, CPU 프로파일, I/O 통계, 메모리 정보, 상위 프로세스를 한 번에 수집하고 perf 보고서를 생성한다.
#!/bin/bash
# 시스템 성능 종합 분석 스크립트
OUTPUT_DIR="perf_analysis_$(date +%Y%m%d_%H%M%S)"
mkdir -p "$OUTPUT_DIR"
echo "Starting comprehensive performance analysis..."
# 1. 시스템 전반적 상태
echo "(1) Collecting system overview..."
vmstat 1 60 > "$OUTPUT_DIR/vmstat.log" &
VMSTAT_PID=$!
# 2. CPU 프로파일링
echo "(2) CPU profiling with perf..."
perf record -g -a -o "$OUTPUT_DIR/perf.data" sleep 30 &
PERF_PID=$!
# 3. I/O 통계
echo "(3) Disk I/O statistics..."
iostat -x 1 60 > "$OUTPUT_DIR/iostat.log" &
IOSTAT_PID=$!
# 4. 메모리 정보
echo "(4) Memory information..."
cat /proc/meminfo > "$OUTPUT_DIR/meminfo.log"
vmstat -s > "$OUTPUT_DIR/vmstat_summary.log"
# 5. 프로세스별 리소스 사용
echo "(5) Top processes..."
top -b -n 10 -d 1 > "$OUTPUT_DIR/top.log" &
TOP_PID=$!
# 대기
wait $VMSTAT_PID $PERF_PID $IOSTAT_PID $TOP_PID
# perf 리포트 생성
perf report -i "$OUTPUT_DIR/perf.data" --stdio > "$OUTPUT_DIR/perf_report.txt"
echo "Analysis complete. Results in $OUTPUT_DIR/"
웹 서버와 데이터베이스에서의 추적 예시
웹 서버의 지연을 조사할 때는 먼저 시스템 전반의 CPU와 I/O 상태를 확인하고, CPU 핫스팟과 시스템 콜 경합을 차례로 추적할 수 있다.
# 1. 전반적 시스템 상태 확인
vmstat 1 10
# 관찰: CPU us/sy 높음, I/O 대기 낮음 → CPU 병목
# 2. CPU 핫스팟 분석
perf top -p $(pgrep nginx)
# 발견: SSL 핸드셰이크가 CPU의 40% 사용
# 3. 시스템 콜 분석
strace -c -p $(pgrep nginx) -f
# 발견: futex 시스템 콜이 과도하게 발생 → 잠금 경합
# 해결: 워커 프로세스 수 증가, SSL 세션 캐싱 활성화
데이터베이스 쿼리 지연에서는 디스크 대기, 파일 관련 시스템 콜, 캐시 미스를 이어서 살필 수 있다.
# 1. I/O 패턴 확인
iostat -x 1 10
# 관찰: await 높음, r/s 많음 → 랜덤 읽기 과다
# 2. 시스템 콜 추적
strace -p $(pgrep postgres) -e trace=file -c
# 발견: pread64가 대부분의 시간 소비
# 3. 캐시 미스 분석
perf stat -e LLC-loads,LLC-load-misses -p $(pgrep postgres) sleep 10
# 발견: LLC 미스율 25% → 메모리 캐시 부족
# 해결: 데이터베이스 버퍼 풀 증가, 인덱스 최적화
perf는 CPU 수준의 상세 프로파일링을, vmstat과 iostat은 시스템 자원 상태를, strace와 ltrace는 애플리케이션의 호출 동작을 보여 준다. 이 도구들을 함께 사용하면 복잡한 성능 문제에서도 병목을 분리하고 최적화 방향을 정할 수 있으며, 지속적인 모니터링으로 사전 대응의 근거를 마련할 수 있다.