성능 최적화 (Performance Optimization)

Linux 커널 성능 최적화: perf, ftrace, io_uring, 프로파일링, 튜닝.

관련 표준: Intel SDM (PMU, 성능 카운터), AMD APM (IBS, 성능 모니터링) — 커널 성능 프로파일링에서 참조하는 하드웨어 성능 모니터링 규격입니다. 종합 목록은 참고자료 — 표준 & 규격 섹션을 참고하세요.

성능 최적화 개요

커널 성능 최적화는 병목 지점을 정확히 파악하는 것에서 시작합니다. Linux는 perf, ftrace, BPF 등 강력한 프로파일링/추적 도구를 기본 제공합니다.

성능 모니터링 원리 (PMU)

커널 성능 분석의 기반은 CPU에 내장된 PMU(Performance Monitoring Unit)입니다. PMU는 하드웨어 수준에서 CPU 이벤트를 카운팅하는 전용 회로로, 소프트웨어 오버헤드 없이 정밀한 성능 데이터를 수집합니다.

PMU 동작 메커니즘

구성 요소역할예시
성능 카운터 레지스터특정 이벤트 발생 횟수를 카운팅x86: PMC0~PMCn (일반적으로 4~8개)
이벤트 선택 레지스터카운팅할 이벤트 종류를 지정cycles, instructions, cache-misses, branch-misses
오버플로 인터럽트카운터가 지정값에 도달하면 인터럽트 발생PMI(Performance Monitoring Interrupt)

샘플링 vs 카운팅

perf는 두 가지 방식으로 PMU를 활용합니다:

이벤트 멀티플렉싱: 하드웨어 PMC 수(보통 4~8개)보다 많은 이벤트를 동시에 모니터링하면, 커널이 시분할로 PMC를 전환합니다. 이 경우 결과에 추정값(<not counted> 또는 스케일링 계수)이 포함될 수 있습니다.

프로파일링 방법론

체계적인 성능 분석 워크플로는 다음 순서를 따릅니다:

  1. 전체 지표 수집 (perf stat): IPC(Instructions Per Cycle), 캐시 미스율, 분기 예측 실패율 등 시스템 전체의 성능 특성을 파악합니다. IPC < 1이면 메모리/I/O 바운드, IPC > 2이면 컴퓨트 바운드 가능성이 높습니다.
  2. 핫스팟 식별 (perf record + Flame Graph): CPU 시간 소모가 집중되는 함수와 콜 체인을 식별합니다.
  3. 정밀 분석 (perf annotate, ftrace): 핫스팟 함수의 명령어별 사이클 분포, 함수 호출 흐름, 지연 원인을 파악합니다.
  4. 가설 검증 및 최적화: 원인에 맞는 최적화를 적용하고 다시 측정하여 효과를 검증합니다.
💡

Brendan Gregg의 USE 방법론: 모든 리소스(CPU, 메모리, 디스크, 네트워크)에 대해 Utilization(사용률), Saturation(포화도), Errors(에러)를 체계적으로 점검합니다. 이 프레임워크를 따르면 병목을 빠르게 좁힐 수 있습니다.

perf 종합 가이드

perf는 Linux 커널에 내장된 성능 분석 프레임워크로, perf_event_open(2) 시스템 콜을 통해 PMU 하드웨어 카운터, 소프트웨어 이벤트, tracepoint, kprobe/uprobe 등을 통합적으로 활용합니다. 위의 PMU 원리 섹션에서 설명한 카운팅/샘플링 모드를 실전에서 사용하는 도구입니다.

설정 및 권한

perf를 사용하려면 커널 설정과 시스템 권한이 필요합니다:

# 필수 커널 설정
CONFIG_PERF_EVENTS=y          # perf_event 서브시스템
CONFIG_HW_PERF_EVENTS=y       # 하드웨어 PMU 지원
CONFIG_DEBUG_INFO=y           # 심볼/소스 매핑 (annotate, probe)
CONFIG_DEBUG_INFO_BTF=y       # BPF 타입 정보 (선택)
CONFIG_KALLSYMS_ALL=y         # 모든 커널 심볼 (권장)

# 설치 (배포판별)
sudo apt install linux-tools-$(uname -r)   # Debian/Ubuntu
sudo dnf install perf                       # Fedora/RHEL
perf_event_paranoid허용 범위설명
-1모든 이벤트, 모든 사용자제한 없음 (개발/테스트 환경)
0커널+사용자 공간CPU 이벤트 허용, raw tracepoint 제한
1 (기본)사용자 공간만커널 프로파일링에 root 또는 CAP_PERFMON 필요
2사용자 공간 (CPU 제한)시스템 전체 모니터링 불가
3거부perf_event_open 완전 차단
# 현재 설정 확인 및 변경
cat /proc/sys/kernel/perf_event_paranoid
sudo sysctl kernel.perf_event_paranoid=-1    # 임시 해제

# Linux 5.8+: CAP_PERFMON capability (root 대신 사용)
sudo setcap cap_perfmon+ep /usr/bin/perf

perf list: 이벤트 탐색

perf가 지원하는 이벤트를 확인합니다. 이벤트는 카테고리별로 분류됩니다:

카테고리예시소스
Hardwarecycles, instructions, cache-misses, branch-missesPMU 카운터
Softwarecontext-switches, page-faults, cpu-migrations커널 소프트웨어 카운터
CacheL1-dcache-load-misses, LLC-load-missesPMU 캐시 이벤트
Tracepointsched:sched_switch, block:block_rq_issue커널 tracepoint
PMUcpu/event=0xc0,umask=0x01/플랫폼 특정 PMU
RawrNNN (예: r003c = unhalted cycles)하드웨어 인코딩 직접 지정
# 전체 이벤트 목록
perf list

# 카테고리별 필터
perf list hw              # 하드웨어 이벤트만
perf list sw              # 소프트웨어 이벤트만
perf list cache           # 캐시 이벤트
perf list tracepoint      # tracepoint 이벤트
perf list pmu             # PMU 특정 이벤트

# 키워드 검색
perf list | grep -i 'branch'

# Raw 이벤트: Intel SDM/AMD APM에서 인코딩 확인
# rNNN 형식: r + EventSelect(8bit) + UnitMask(8bit)
perf stat -e r003c ./program   # CPU_CLK_UNHALTED.CORE

perf stat: 이벤트 카운팅 심화

perf stat은 카운팅 모드로 이벤트 총계를 수집합니다. 기본 사용법은 디버깅 페이지를 참조하고, 여기서는 분석적 해석에 집중합니다.

# 상세 카운터 (-d: L1, -dd: L1+LLC, -ddd: L1+LLC+TLB+분기)
perf stat -ddd ./program

# 반복 측정으로 통계적 신뢰도 확보
perf stat -r 5 -e cycles,instructions ./program
# 출력: 평균 ± 표준편차 (stddev)

# 인터벌 모드: 1초 간격으로 카운터 출력 (추세 분석)
perf stat -I 1000 -e cycles,instructions -a

# 이벤트 그룹: 동일 PMC 타임슬라이스에서 측정 (비율 정확도 향상)
perf stat -e '{cycles,instructions}' ./program

# CPU별 통계
perf stat -e cycles -A -a -- sleep 5
💡

IPC 해석 가이드:

  • IPC < 1.0: 메모리/I/O 바운드 가능성 — 캐시 미스, TLB 미스, 메모리 대역폭 포화 확인
  • IPC 1.0~2.0: 혼합 워크로드 — 분기 예측 실패, 파이프라인 스톨 확인
  • IPC > 2.0: 컴퓨트 바운드 — 알고리즘/SIMD 최적화가 효과적

cache-misses / cache-references 비율이 5% 이상이면 캐시 최적화가 필요합니다.

perf record / report: 샘플링 프로파일링

perf record는 샘플링 모드로 프로파일 데이터를 perf.data 파일에 기록하고, perf report로 분석합니다.

# 샘플링 주파수 vs 주기
perf record -F 99 ./program          # -F: 초당 99 샘플 (주파수)
perf record -c 100000 ./program      # -c: 100000 이벤트마다 1 샘플 (주기)
# -F 99: 커널이 주파수를 유지하도록 주기를 자동 조절 (권장)
# -c: 정확한 이벤트 수 기준 (이벤트 빈도가 변할 때 유용)

# 콜 그래프 포함 기록 (다음 섹션에서 방법 비교)
perf record -g -F 99 -p $(pidof myapp) -- sleep 30

# 시스템 전체 + 커널 심볼
perf record -ag -F 99 -- sleep 10

# report 주요 옵션
perf report                          # TUI 모드 (대화식)
perf report --stdio                  # 텍스트 출력 (스크립트/로그용)
perf report --hierarchy              # 콜 체인 계층 구조
perf report --sort=dso,sym           # 라이브러리/심볼별 정렬
perf report --percent-limit=1        # 1% 미만 항목 필터링

콜 그래프 수집 방법 비교

perf record -g로 콜 그래프(콜 스택)를 수집할 때 세 가지 방법을 선택할 수 있으며, 각각 트레이드오프가 다릅니다:

방법옵션오버헤드정확도스택 깊이요구사항
Frame Pointer (fp)--call-graph fp최소중간무제한-fno-omit-frame-pointer 컴파일
DWARF--call-graph dwarf높음높음무제한CONFIG_DEBUG_INFO, 디버그 심볼
LBR--call-graph lbr최소높음8~32단계Intel CPU (Haswell+), CONFIG_PERF_EVENTS_INTEL_LBR
# Frame Pointer: 빠르지만 -fno-omit-frame-pointer로 빌드된 코드 필요
perf record --call-graph fp -F 99 ./program

# DWARF: 가장 정확하지만 perf.data 크기 큼 (스택 덤프 저장)
perf record --call-graph dwarf,32768 -F 99 ./program
# 32768 = 스택 덤프 크기 (기본 8192, 깊은 스택이면 증가)

# LBR: Intel CPU에서 하드웨어 지원, 낮은 오버헤드 + 높은 정확도
perf record --call-graph lbr -F 99 ./program
💡

콜 그래프 방법 선택 가이드: 커널 프로파일링은 fp가 기본(커널은 frame pointer 사용). 사용자 공간은 dwarf가 가장 정확하며, Intel 환경에서 오버헤드가 문제면 lbr을 선택하세요. -g만 쓰면 기본값은 fp입니다.

perf annotate: 명령어 수준 분석

perf annotate는 핫스팟 함수의 어셈블리/소스 코드에 샘플 분포를 매핑하여, 어떤 명령어가 가장 많은 사이클을 소모하는지 보여줍니다.

# 기본 사용법 (perf record 후)
perf record -g -F 99 ./program
perf annotate                         # TUI: 심볼 선택 → 명령어별 비율
perf annotate --symbol=hot_function   # 특정 함수 직접 지정

# 소스 코드 인터리빙 (CONFIG_DEBUG_INFO 필요)
perf annotate --source               # 소스 + 어셈블리 동시 표시
perf annotate --no-source            # 어셈블리만 표시

# stdio 출력 (스크립트/분석용)
perf annotate --stdio --symbol=copy_page

annotate 출력 예시 — 각 어셈블리 명령어 앞에 해당 명령어의 샘플 비율(%)이 표시됩니다:

       │   copy_page():
  0.50 │   mov    (%rsi),%rax
 45.20 │   mov    %rax,(%rdi)      ← 캐시 미스로 스톨 (핫 명령어)
  0.30 │   mov    0x8(%rsi),%rax
  2.10 │   mov    %rax,0x8(%rdi)
         │   ...

핫 명령어 해석: mov 명령어에 높은 비율이 나타나면 대개 캐시 미스(메모리 스톨)가 원인입니다. 이때 perf stat -e L1-dcache-load-misses와 함께 확인하세요. div/idiv에 높은 비율이면 정수 나눗셈 비용, 분기 명령에 높으면 분기 예측 실패를 의심합니다.

perf top: 실시간 모니터링

perf toptop 명령어처럼 실시간으로 CPU를 가장 많이 소모하는 함수를 보여줍니다.

# 시스템 전체 실시간 프로파일링
perf top                              # 기본: cycles 이벤트
perf top -g                           # 콜 그래프 포함

# 특정 프로세스 / 이벤트 필터링
perf top -p $(pidof myapp)            # PID 기반
perf top -e cache-misses              # 캐시 미스 기준 정렬

# TUI에서 심볼 선택 후 Enter → annotate 뷰 (명령어별 분석)
# 's' 키: 심볼 필터, 'K': 커널 심볼 토글

perf trace: 시스템 콜 추적

perf tracestrace와 유사하지만, 커널 tracepoint 기반으로 동작하여 오버헤드가 훨씬 낮습니다.

특성straceperf trace
메커니즘ptrace (프로세스 중단)perf_event tracepoint
오버헤드높음 (2~10x 느려짐)낮음 (<5%)
시스템 전체PID별만 가능-a로 시스템 전체
통계 모드-c-s (더 상세)
이벤트 확장시스콜만시스콜 + page-fault + 기타 이벤트
# 기본 사용법
perf trace ./program                  # 새 프로세스 추적
perf trace -p $(pidof myapp)          # 실행 중인 프로세스

# 필터링
perf trace -e open,read,write ./program      # 특정 시스콜만
perf trace --duration 10 -p 1234             # 10ms 이상 소요된 콜만

# 요약 모드: 시스콜별 횟수/시간 통계
perf trace -s ./program
# 출력: syscall  calls  errors  total(ms)  min(ms)  avg(ms)  max(ms)

# 시스템 전체 + page fault 포함
perf trace -a -e 'major-faults,minor-faults' -- sleep 5

perf c2c: False Sharing 탐지

perf c2c(cache-to-cache)는 HITM(Hit in Modified) 이벤트를 분석하여, 여러 CPU 코어가 동일 캐시라인을 경쟁적으로 수정하는 false sharing을 탐지합니다.

# 1단계: 메모리 접근 샘플 기록
perf c2c record -a -- sleep 10
# 또는 특정 프로세스
perf c2c record -p $(pidof myapp) -- sleep 10

# 2단계: HITM 분석 리포트
perf c2c report --stdio
# Shared Data Cache Line Table에서:
# - Rmt HITM: 원격 소켓에서 수정된 라인 접근 (가장 비쌈)
# - Lcl HITM: 같은 소켓 내 다른 코어에서 수정된 라인 접근

# 3단계: 핫 캐시라인의 오프셋 + 데이터 소스 확인
# → struct 멤버 분리 또는 ____cacheline_aligned 적용

캐시 코히런시 프로토콜(MESI/MOESI)과 false sharing의 원리, ____cacheline_aligned 해결 기법 등 상세 내용은 CPU 캐시 — False Sharing 페이지를 참고하세요.

perf diff: 프로파일 비교

perf diff는 두 개의 perf.data 파일을 비교하여 최적화 전후의 성능 변화를 정량적으로 분석합니다.

# A/B 테스트 워크플로

# 1. 최적화 전 프로파일 기록
perf record -g -F 99 -o baseline.data -- ./program_v1

# 2. 최적화 후 프로파일 기록
perf record -g -F 99 -o optimized.data -- ./program_v2

# 3. 비교 분석
perf diff baseline.data optimized.data
# 출력 컬럼:
#   Baseline  Delta    Symbol
#   --------  -----    ------
#   15.30%    -8.20%   hot_function    ← 8.2% 감소 (개선)
#    3.10%    +2.50%   new_function    ← 2.5% 증가 (회귀)

# delta 기준 정렬
perf diff --sort=delta baseline.data optimized.data

perf bench: 내장 벤치마크

perf bench는 커널/하드웨어 서브시스템의 기본 성능을 측정하는 마이크로벤치마크 모음입니다. 시스템 설정 변경이나 커널 업그레이드 전후 비교에 유용합니다.

카테고리벤치마크측정 대상
schedmessaging, pipe스케줄러 컨텍스트 스위치, IPC 성능
memmemcpy, memset메모리 대역폭
numamemNUMA 노드 간 메모리 접근 지연
futexhash, wake, requeue, lock-pifutex 서브시스템 성능
epollwait, ctlepoll 이벤트 처리 성능
# 스케줄러: 메시지 패싱 성능 (프로세스/스레드 간)
perf bench sched messaging -g 20 -t -l 1000
# -g 20: 20개 그룹, -t: 스레드 사용, -l 1000: 1000회 반복

# 메모리: memcpy 대역폭
perf bench mem memcpy -s 4GB -l 5

# futex: 잠금 성능 (nthread별)
perf bench futex lock-pi -t 8

# NUMA: 노드 간 메모리 접근
perf bench numa mem -p 4 -t 4 -P 1024 -T 0

# 전체 벤치마크 실행
perf bench all

Intel/AMD 플랫폼별 PMU

범용 이벤트(cycles, instructions) 외에, 플랫폼별 PMU 확장 기능을 활용하면 더 정밀한 분석이 가능합니다.

Intel PEBS (Precise Event-Based Sampling)

PEBS는 이벤트 발생 시점의 정확한 IP(Instruction Pointer)를 하드웨어가 기록합니다. 일반 샘플링의 "skid"(인터럽트 지연으로 인한 IP 부정확) 문제를 해결합니다.

# PEBS 이벤트: 이벤트명 뒤에 :p 또는 :pp 수정자
# :p = precise level 1, :pp = precise level 2 (최대 정밀도)
perf record -e cycles:pp -F 99 ./program
perf record -e mem-loads:pp -F 97 ./program   # 메모리 로드 정밀 샘플링

# PEBS + annotate로 정확한 명령어별 분석
perf annotate --symbol=hot_function

AMD IBS (Instruction-Based Sampling)

IBS는 명령어 파이프라인에서 직접 샘플링하여 PEBS와 유사한 정밀도를 제공합니다. Fetch와 Op 두 가지 모드가 있습니다.

# AMD IBS Fetch 샘플링
perf record -e ibs_fetch// -c 100000 ./program

# AMD IBS Op 샘플링 (실행된 마이크로-op 기반)
perf record -e ibs_op// -c 100000 ./program

# IBS + 메모리 접근 분석
perf mem record -- ./program    # AMD에서 자동으로 IBS 사용

플랫폼별 유용 이벤트

이벤트플랫폼용도
mem-loads:pp, mem-stores:ppIntel (PEBS)메모리 접근 지연/소스 분석
ibs_op//, ibs_fetch//AMD (IBS)명령어/페치 수준 정밀 분석
topdown-*Intel (Skylake+)Top-Down 마이크로아키텍처 분석
offcore_responseIntelL3 미스 후 메모리 응답 소스 분석
cpu/event=0x...,umask=0x.../공통벤더 문서의 raw 이벤트 직접 지정

MSR 레지스터를 통한 PMU 제어, HWP/RAPL 등 하드웨어 성능 모니터링의 저수준 세부사항은 MSR 레지스터 페이지를 참고하세요.

Flame Graph 분석

Flame Graph는 CPU 프로파일 데이터를 스택 깊이별로 시각화하여 핫 코드 경로를 직관적으로 식별합니다:

# On-CPU Flame Graph
perf record -F 99 -ag -- sleep 30
perf script > out.perf
stackcollapse-perf.pl out.perf > out.folded
flamegraph.pl out.folded > cpu_flame.svg

# Off-CPU Flame Graph (블로킹 시간 분석)
# BPF 기반 (bcc tools)
offcputime-bpfcc -df -p $(pidof myapp) 30 > offcpu.folded
flamegraph.pl --color=io offcpu.folded > offcpu_flame.svg

# Memory allocation Flame Graph
perf record -e kmem:kmalloc -ag -- sleep 10
perf script | stackcollapse-perf.pl | flamegraph.pl > mem_flame.svg

Differential Flame Graph

perf diff의 결과를 시각화하여 최적화 전후 변화를 색상으로 표현합니다:

# 최적화 전/후 프로파일 수집
perf record -F 99 -ag -o before.data -- ./workload_v1
perf record -F 99 -ag -o after.data -- ./workload_v2

# Differential Flame Graph 생성
perf script -i before.data | stackcollapse-perf.pl > before.folded
perf script -i after.data | stackcollapse-perf.pl > after.folded
difffolded.pl before.folded after.folded | flamegraph.pl > diff_flame.svg
# 빨간색: 증가 (회귀), 파란색: 감소 (개선)

Intel® PCM (Performance Counter Monitor)

Intel PCM은 Intel이 개발한 오픈소스 성능 모니터링 도구 모음으로, CPU 코어 성능 카운터, 메모리 대역폭, QPI/UPI 링크 사용률, PCIe 대역폭, 전력 소비량 등을 실시간으로 측정합니다. perf가 커널에 내장된 범용 프로파일링 프레임워크라면, PCM은 Intel 플랫폼에 특화된 시스템 수준 하드웨어 모니터링 도구입니다.

PCM vs perf: perf는 커널 perf_event 서브시스템을 통해 PMU에 접근하며 프로세스/함수 수준 프로파일링에 강합니다. 반면 PCM은 MSR/PCI config 레지스터에 직접 접근하여 언코어(Uncore) 카운터 — 메모리 컨트롤러, QPI/UPI 링크, PCIe, 전력 등 코어 외부 리소스 — 를 포함한 시스템 전체 관점의 모니터링에 특화되어 있습니다.

PCM 아키텍처 개요

PCM은 세 가지 경로로 하드웨어 카운터에 접근합니다:

User Space pcm (Core 카운터) pcm-memory (메모리 BW) pcm-pcie (PCIe BW) pcm-power (전력/온도) pcm-latency (메모리 레이턴시) pcm-sensor-server (REST API/Grafana) Kernel Space /dev/cpu/*/msr (MSR) perf_event_open() (PMU) sysfs / MMIO (TPMI) Hardware (CPU / Uncore) Core PMU PMC, Fixed CTR Uncore PMU CBox, iMC, UPI 메모리 컨트롤러 iMC 카운터 RAPL PKG/DRAM 에너지 PCIe / CXL IIO 카운터
접근 경로대상 카운터커널 요구사항용도
MSR 드라이버Core PMU, Fixed CTR, RAPLmsr 커널 모듈코어별 성능 카운터, 전력 측정
perf_eventCore/Uncore PMUCONFIG_PERF_EVENTSperf 서브시스템 경유 (권한 제어 용이)
sysfs/MMIOTPMI, PCI config spaceTPMI 드라이버 (6.3+)언코어 카운터, PCIe/CXL 모니터링

설치 및 빌드

# 소스에서 빌드 (GitHub)
git clone --recursive https://github.com/intel/pcm.git
cd pcm
mkdir build && cd build
cmake ..
cmake --build . --parallel

# 패키지 매니저로 설치 (배포판별)
sudo apt install pcm              # Ubuntu 22.04+ / Debian
sudo dnf install pcm              # Fedora / RHEL 9+

# Docker로 실행 (권한 필요)
docker run --privileged -d \
  --name pcm --ipc=host --pid=host \
  -v /sys:/sys:rw \
  ghcr.io/intel/pcm

커널 모듈 및 접근 권한 설정

PCM은 MSR 레지스터에 직접 접근하므로 msr 커널 모듈과 root 권한(또는 CAP_SYS_RAWIO)이 필요합니다:

# msr 커널 모듈 로드
sudo modprobe msr

# NMI watchdog 비활성화 (PMU 카운터 점유 방지)
# NMI watchdog가 고정 카운터를 사용하면 PCM과 충돌
sudo sysctl kernel.nmi_watchdog=0

# Secure Boot 환경에서 MSR 접근 허용
# /dev/cpu/*/msr 접근이 차단될 경우:
sudo modprobe msr allow_writes=on

# perf_event 기반 접근 사용 시 (MSR 직접 접근 대신)
# PCM은 perf_event 모드도 지원 (-e 옵션 또는 환경변수)
export PCM_USE_PERF=1
sudo sysctl kernel.perf_event_paranoid=-1

NMI watchdog 충돌: NMI watchdog는 고정 카운터(INST_RETIRED.ANY)를 점유합니다. PCM 실행 전 nmi_watchdog=0으로 비활성화하지 않으면 카운터 프로그래밍이 실패하거나 부정확한 결과가 나올 수 있습니다. PCM은 시작 시 이 충돌을 자동 감지하고 경고합니다.

핵심 도구 모음

PCM은 목적별로 분리된 여러 도구를 제공합니다. 각 도구는 Intel CPU의 특정 하드웨어 카운터에 최적화되어 있습니다.

pcm: 코어 성능 카운터

기본 도구로, 코어별 IPC(Instructions Per Cycle), L2/L3 캐시 히트율, 분기 예측률 등 핵심 지표를 실시간 표시합니다.

# 기본 실행: 1초 간격으로 코어별 성능 카운터 표시
sudo pcm

# 측정 간격 및 반복 횟수 지정
sudo pcm 0.5 -i=20   # 0.5초 간격, 20회 측정

# CSV 출력 (후처리/시각화용)
sudo pcm 1 -csv=result.csv

# 특정 프로그램 실행 동안 측정
sudo pcm -- ./benchmark

# 코어 이벤트 커스텀 지정 (최대 4개 범용 카운터)
sudo pcm -e core/config=0x2e,config1=0x41,name=LLC_MISSES/

pcm 출력의 주요 지표:

지표설명정상 범위이상 징후
IPCInstructions Per Cycle1.0~4.0< 0.5이면 심각한 메모리 스톨
L2 Hit RatioL2 캐시 히트율> 95%< 80%이면 작업 셋 > L2
L3 Hit RatioL3 (LLC) 캐시 히트율> 80%< 50%이면 메모리 대역폭 확인 필요
FREQ실제 동작 주파수 (GHz)부스트 근처기본 클럭 이하이면 전력/열 제한
TEMP코어 온도 (°C)< TjMax-10TjMax 도달 시 스로틀링
INST은퇴된 명령어 수워크로드 의존코어 간 불균형 → 부하 분산 문제
AFREQActive Frequency (활성 시 주파수)≈ Max Turbo기본 클럭 근처이면 전력 제한
L3MISSL3 캐시 미스 횟수워크로드 의존높으면 메모리 BW 병목

pcm-memory: 메모리 대역폭 모니터링

소켓/채널별 메모리 대역폭(Read/Write/Total)을 iMC(Integrated Memory Controller) 카운터로 실시간 측정합니다. NUMA 환경에서 메모리 병목 진단에 필수적입니다.

# 소켓/채널별 메모리 대역폭 측정
sudo pcm-memory

# 0.5초 간격, 파일 출력
sudo pcm-memory 0.5 -csv=mem_bw.csv

# 특정 소켓만 모니터링
sudo pcm-memory -s 0  # 소켓 0만

# 출력 예시:
#  Skt | Read(GB/s) | Write(GB/s) | PMM Read | PMM Write | Total(GB/s)
#  ---+------------+-------------+----------+-----------+------------
#   0  |    45.2    |    12.8     |   N/A    |    N/A    |    58.0
#   1  |    43.8    |    11.5     |   N/A    |    N/A    |    55.3
# ---+------------+-------------+----------+-----------+------------
# System|   89.0    |    24.3     |   N/A    |    N/A    |   113.3
💡

메모리 대역폭 포화 판단: 이론적 최대 대역폭은 채널 수 × DDR 전송률 × 8바이트로 계산됩니다. 예: 6채널 DDR5-4800 = 6 × 4800MT/s × 8B ≈ 230 GB/s. 측정값이 이론값의 70% 이상이면 메모리 BW 포화 상태입니다. perf stat -e LLC-load-misses와 함께 확인하세요.

pcm-pcie: PCIe 대역폭 모니터링

IIO(I/O 유닛) 언코어 카운터를 통해 PCIe 포트별 인바운드/아웃바운드 대역폭을 측정합니다. NVMe SSD, GPU, 네트워크 카드 등의 I/O 병목 진단에 사용합니다.

# PCIe 포트별 대역폭 (GB/s)
sudo pcm-pcie

# 이벤트 모드: Part0~Part3 상세 분류
sudo pcm-pcie -e

# 특정 BDF (Bus:Device.Function) 필터링
sudo pcm-pcie -B 0x3a:0x00.0

# CSV 출력
sudo pcm-pcie 1 -csv=pcie_bw.csv

# CXL 메모리 대역폭 모니터링 (지원 플랫폼)
sudo pcm-pcie -cxl

pcm-power: 전력 및 열 모니터링

RAPL(Running Average Power Limit) MSR과 온도 센서를 통해 패키지/DRAM/PP0/PP1별 전력 소비와 코어 온도, C-State 상주 비율을 실시간으로 표시합니다.

# 전력/온도/C-State 모니터링
sudo pcm-power

# 출력 예시:
# Package 0: Consumed energy (Joules): 85.2 | Thermal headroom: 23°C
# Package 0: C2 residency: 45.2% | C6 residency: 32.1%
# DRAM energy: 12.8 J

# 전력 변화 추세 관찰 (CSV)
sudo pcm-power 1 -csv=power.csv

pcm-latency: 메모리 레이턴시 측정

메모리 접근 레이턴시를 측정합니다. NUMA 환경에서 로컬/원격 메모리 접근 지연 차이를 정량적으로 파악할 수 있습니다.

# 메모리 레이턴시 측정
sudo pcm-latency

# 특정 소켓 대상
sudo pcm-latency -s 0

pcm-numa: NUMA 트래픽 분석

NUMA 환경에서 로컬/원격 메모리 접근 비율을 측정하여 메모리 배치 최적화 기회를 식별합니다.

# NUMA 로컬/원격 메모리 접근 비율 측정
sudo pcm-numa

# 출력 예시:
# Socket 0: Local Memory Accesses: 95.2% | Remote: 4.8%
# Socket 1: Local Memory Accesses: 87.3% | Remote: 12.7%  ← 최적화 필요

# NUMA 최적화 확인: 원격 접근이 10% 이상이면
# numactl --membind 또는 cpuset으로 바인딩 조정 필요

pcm-iio: I/O 유닛 통계

IIO(I/O 유닛) 스택별 인바운드/아웃바운드 트래픽을 상세 분석합니다. PCIe 디바이스와 CPU 소켓 간 데이터 흐름을 파악합니다.

# I/O 유닛(IIO) 스택별 트래픽
sudo pcm-iio

# CSV 출력
sudo pcm-iio 1 -csv=iio.csv

pcm-raw: Raw 카운터 프로그래밍

사전 정의 도구로 측정할 수 없는 커스텀 이벤트를 JSON 기반 이벤트 정의 파일로 프로그래밍합니다. Intel SDM의 이벤트 코드를 직접 지정할 수 있습니다.

# JSON 이벤트 정의 파일 사용
sudo pcm-raw -e events.json

# 이벤트 정의 예시 (events.json):
# {
#   "core": {
#     "programmable": [
#       { "name": "L2_MISS", "event": "0x2e", "umask": "0x41" },
#       { "name": "DTLB_MISS", "event": "0x08", "umask": "0x20" }
#     ]
#   }
# }

# PCM 배포에 포함된 사전 정의 이벤트
ls /usr/share/pcm/PMURegisterDeclarations/
# → SPR/ ICX/ SKX/ ... (마이크로아키텍처별 이벤트 파일)

pcm-sensor-server: 원격 모니터링 (REST API / Grafana)

pcm-sensor-server는 PCM 데이터를 HTTP/HTTPS REST API로 노출하여, Grafana, Prometheus, Telegraf 등 외부 모니터링 시스템과 통합합니다.

# REST API 서버 시작 (기본 포트: 9738)
sudo pcm-sensor-server

# HTTPS + 포트 지정
sudo pcm-sensor-server -p 19738 --https 443 \
  --key server.key --cert server.crt

# JSON 데이터 조회
curl -s http://localhost:9738/metrics | head -20
# Prometheus 형식 메트릭 노출 → Grafana 대시보드 연동

# Grafana 대시보드 활용
# PCM 소스의 grafana/ 디렉터리에 사전 정의 대시보드 JSON 포함
# → Grafana에서 Import하면 코어/메모리/PCIe/전력 대시보드 즉시 사용

pcm-tpmi: Topology Aware Register & PM Interface (6.3+)

Sapphire Rapids 이후 서버 플랫폼에서 TPMI(Topology Aware Register and PM Interface)를 통해 언코어 카운터에 접근합니다. MSR 대신 MMIO 기반으로 동작하여 Secure Boot 환경에서도 사용 가능합니다.

# TPMI 기반 언코어 카운터 접근
sudo pcm-tpmi

# TPMI 지원 확인
ls /sys/bus/auxiliary/devices/ | grep intel_vsec
# intel_vsec 드라이버가 로드되어 있으면 TPMI 지원

실전 활용 시나리오

시나리오 1: 메모리 대역폭 포화 진단

애플리케이션이 CPU 사용률은 높지만 IPC가 낮은 경우, 메모리 대역폭 포화가 원인일 수 있습니다:

# 1단계: IPC 확인 → 메모리 바운드 여부 판단
sudo pcm 1 -i=5
# → IPC < 1.0 + L3 Hit Ratio < 50% → 메모리 바운드 의심

# 2단계: 메모리 대역폭 측정
sudo pcm-memory 0.5
# → Read BW가 이론값의 70% 이상이면 BW 포화
# → 채널 간 불균형이 크면 DIMM 구성 확인

# 3단계: NUMA 배치 확인
sudo pcm-numa
# → Remote Access > 10%이면 메모리 배치 최적화
# → numactl --membind=0 ./app 으로 로컬 바인딩

# 4단계: perf로 핫스팟 함수의 LLC 미스 확인
perf record -e LLC-load-misses:pp -c 10000 -- ./app
perf report

시나리오 2: PCIe I/O 병목 진단

# NVMe/GPU가 예상 성능에 미달할 때

# 1단계: PCIe 대역폭 측정
sudo pcm-pcie 1
# → 디바이스별 인바운드/아웃바운드 BW 확인
# → Gen4 x16: 이론 31.5 GB/s, 실측이 50% 미만이면 문제

# 2단계: IIO 스택별 상세 분석
sudo pcm-iio 1
# → 어느 IIO 스택에서 병목이 발생하는지 파악

# 3단계: 전력 제한 확인 (전력 제한으로 I/O 성능 저하 가능)
sudo pcm-power 1
# → PKG 전력이 TDP 근처이면 전력 스로틀링

시나리오 3: 코어 주파수 스로틀링 진단

# 성능이 간헐적으로 저하될 때 (열/전력 제한 의심)
sudo pcm 0.5 -csv=freq_trace.csv -i=60
# → FREQ/AFREQ 컬럼에서 주파수 변동 추적
# → TEMP가 TjMax에 근접하면 열 스로틀링
# → C6 residency가 높으면 idle 상태 비율 과다

# turbostat 병행 (PCM과 보완적)
sudo turbostat --interval 1 --show Core,CPU,Avg_MHz,Busy%,Bzy_MHz,PkgWatt
# Busy% 100%인데 Bzy_MHz < Max Turbo이면 전력/열 제한

PCM과 대안 도구 비교

도구제공자카운터 접근강점제한
Intel PCMIntel (오픈소스)MSR, perf_event, MMIO언코어 카운터 (iMC, UPI, IIO) 통합, REST APIIntel CPU 전용
perf커널 내장perf_event범용 프로파일링, 프로세스/함수 수준 분석언코어 카운터 설정 복잡
turbostat커널 소스 포함MSR주파수/전력/C-State 특화, 커널과 함께 배포성능 카운터 제한적
pmu-tools (toplev)Andi Kleenperf 위에 구축Top-Down 마이크로아키텍처 분석 (TMA) 자동화설정 복잡, Intel 전용
likwidRRZE (독일)MSR, perf_eventIntel + AMD 지원, 그룹 기반 측정언코어 카운터 PCM보다 제한적

Top-Down 마이크로아키텍처 분석 (TMA) 연계

Intel의 Top-Down Microarchitecture Analysis (TMA) 방법론은 CPU 파이프라인의 병목을 4개 대분류(Frontend Bound, Backend Bound, Bad Speculation, Retiring)로 분류합니다. PCM과 pmu-tools/toplev을 결합하면 체계적인 병목 분석이 가능합니다.

Pipeline Slots (100%) Frontend Bound Bad Speculation Backend Bound Retiring Fetch Latency Fetch BW Branch Mispr. Machine Clears Memory Bound Core Bound Base Micro Seq. L1/L2/L3 Bound DRAM Bound Store Bound pcm → IPC/L3 히트율 | pcm-memory → DRAM BW | toplev → TMA Level 1~6 자동 분류
# pmu-tools 설치
git clone https://github.com/andikleen/pmu-tools.git
cd pmu-tools

# toplev: TMA Level 1 (대분류) 분석
sudo python3 toplev.py --core S0-C0 -l1 -v -- ./benchmark
# 출력: FE(Frontend) 30%, BE(Backend) 45%, BadSpec 5%, Retiring 20%
# → Backend Bound가 지배적 → 메모리/코어 바운드 분석 필요

# Level 2: Backend Bound 상세 분해
sudo python3 toplev.py --core S0-C0 -l2 -v -- ./benchmark
# → Memory Bound 35%, Core Bound 10%

# Level 3+: Memory Bound 세부 원인
sudo python3 toplev.py --core S0-C0 -l3 --nodes '!+Memory*' -v -- ./benchmark
# → L3 Bound 8%, DRAM Bound 22%, Store Bound 5%
# → pcm-memory로 DRAM BW 포화 확인

# PCM + toplev 병행 워크플로
# 1. pcm: 전체 시스템 IPC/캐시/주파수 개요 → 이상 징후 파악
# 2. toplev -l1~l3: 병목 카테고리 좁히기
# 3. pcm-memory/pcm-pcie: 구체적 하드웨어 병목 수치 확인
# 4. perf record + annotate: 함수/명령어 수준 최적화

커널 드라이버 및 관련 소스

PCM이 내부적으로 사용하는 커널 인프라:

커널 드라이버/인터페이스경로역할
msr 모듈arch/x86/kernel/msr.c/dev/cpu/N/msr 문자 장치 제공
intel_uncore PMUarch/x86/events/intel/uncore*.cperf 서브시스템에 언코어 PMU 등록
intel_rapldrivers/powercap/intel_rapl_*.cRAPL 전력 측정 (powercap 프레임워크)
intel_vsec/tpmidrivers/platform/x86/intel/tpmi.cTPMI 레지스터 MMIO 접근 (6.3+)
intel-cstate PMUarch/x86/events/intel/cstate.cC-State 상주 시간 카운터
PCI config space/sys/bus/pci/devices/*/config언코어 PCI 레지스터 접근 (iMC, UPI)
/* PCM이 MSR을 읽는 커널 경로 (arch/x86/kernel/msr.c) */
static ssize_t msr_read(struct file *file, char __user *buf,
                       size_t count, loff_t *ppos)
{
    u32 __user *tmp = (u32 __user *)buf;
    u32 data[2];
    u32 reg = *ppos;       /* MSR 주소 = file offset */
    int cpu = iminor(file->f_path.dentry->d_inode);
    int err;

    /* 해당 CPU에서 RDMSR 실행 */
    err = rdmsr_safe_on_cpu(cpu, reg, &data[0], &data[1]);
    if (err)
        return -EIO;

    if (copy_to_user(tmp, &data, 8))
        return -EFAULT;
    return 8;
}

/* PCM의 실제 MSR 읽기 (user space → /dev/cpu/N/msr) */
/* pread(fd, &data, sizeof(data), MSR_ADDR) */
/* 예: pread(fd, &val, 8, 0x38F) → IA32_PERF_GLOBAL_CTRL */
# PCM에 필요한 커널 설정
CONFIG_X86_MSR=m                   # /dev/cpu/*/msr (필수)
CONFIG_PERF_EVENTS=y               # perf_event 모드 사용 시
CONFIG_INTEL_UNCORE=m              # 언코어 PMU (perf_event 경유 시)
CONFIG_INTEL_RAPL=m                # RAPL 전력 측정
CONFIG_INTEL_VSEC=m                # TPMI 지원 (SPR+ 서버)
CONFIG_INTEL_PMT_TELEMETRY=m       # PMT 텔레메트리

# msr 모듈 자동 로드 설정
echo "msr" | sudo tee /etc/modules-load.d/msr.conf
💡

perf_event 모드 vs MSR 직접 접근: PCM_USE_PERF=1 환경 변수를 설정하면 PCM이 MSR 직접 접근 대신 perf_event_open()을 통해 카운터에 접근합니다. 이 모드는 msr 커널 모듈이 불필요하고, perf_event_paranoid로 권한을 세밀하게 제어할 수 있습니다. 다만 일부 언코어 카운터는 perf_event로 접근이 불가하므로 MSR 모드가 더 완전한 데이터를 제공합니다.

ftrace

ftrace는 커널 내장 추적 프레임워크입니다. 함수 호출, 이벤트, 지연 시간 등을 추적합니다. ftrace의 핵심 원리는 동적 계측(dynamic instrumentation)입니다 — 커널 컴파일 시 모든 함수 진입점에 nop 명령어를 삽입하고, 추적 활성화 시 이를 trampoline 호출로 교체하여 함수 진입/종료를 기록합니다. 비활성 상태에서는 nop이므로 오버헤드가 거의 없습니다.

# ftrace 디렉터리
cd /sys/kernel/tracing  # 또는 /sys/kernel/debug/tracing

# 함수 추적
echo function > current_tracer
echo do_sys_openat2 > set_ftrace_filter
echo 1 > tracing_on
cat trace
echo 0 > tracing_on

# 함수 호출 그래프
echo function_graph > current_tracer
echo vfs_read > set_graph_function
echo 1 > tracing_on

# 이벤트 추적
echo 1 > events/sched/sched_switch/enable
echo 1 > tracing_on
cat trace_pipe

io_uring

io_uring은 Linux 5.1에서 도입된 비동기 I/O 인터페이스로, 공유 링 버퍼를 통해 시스템 콜 오버헤드를 최소화합니다. SQPOLL+IOPOLL 모드에서는 시스템 콜과 인터럽트 없이 I/O를 처리할 수 있습니다.

💡

io_uring의 상세 아키텍처, 커널 내부 구현, liburing 예제, 보안 고려사항 등은 io_uring 전용 페이지를 참고하세요.

커널 튜닝 파라미터

파라미터경로설명
swappiness/proc/sys/vm/swappiness스왑 적극성 (0-200)
dirty_ratio/proc/sys/vm/dirty_ratiodirty 페이지 비율 임계값
tcp_rmem/proc/sys/net/ipv4/tcp_rmemTCP 수신 버퍼 크기
tcp_wmem/proc/sys/net/ipv4/tcp_wmemTCP 송신 버퍼 크기
nr_hugepages/proc/sys/vm/nr_hugepagesHuge page 수
sched_latency_ns/proc/sys/kernel/sched_latency_nsCFS 스케줄링 주기

컴파일러 최적화 힌트

/* Branch prediction hints */
if (likely(condition))    /* 대부분 true */
    fast_path();
if (unlikely(error))     /* 대부분 false */
    handle_error();

/* Cache prefetch */
prefetch(ptr);            /* L1 캐시로 미리 로드 */
prefetchw(ptr);           /* 쓰기 의도로 미리 로드 */

/* Hot/Cold function sections */
void __hot fast_func(void);     /* .text.hot 섹션 */
void __cold error_func(void);   /* .text.unlikely 섹션 */

/* Cache-line alignment */
struct my_data {
    atomic_t counter;
    char padding[60];   /* 캐시라인 경계 정렬 */
} ____cacheline_aligned;
💡

perf stat -d로 L1/LLC 캐시 미스율을 확인하세요. 캐시 미스가 많으면 자료구조의 캐시라인 정렬과 메모리 접근 패턴 최적화가 필요합니다.

BPF 기반 프로파일링

도구 (bcc/bpftrace)용도
funclatency커널 함수 실행 시간 히스토그램
biolatency블록 I/O 지연 시간 분포
runqlat런큐 지연 시간 (스케줄링 대기)
cachestat페이지 캐시 히트/미스율
tcpretransTCP 재전송 추적
hardirqs/softirqs인터럽트 처리 시간
# bpftrace: 함수별 실행 시간 히스토그램
bpftrace -e 'kprobe:vfs_read { @start[tid] = nsecs; }
  kretprobe:vfs_read /@start[tid]/ {
    @us = hist((nsecs - @start[tid]) / 1000);
    delete(@start[tid]);
  }'

# 블록 I/O 지연 시간 분석
biolatency-bpfcc -mD 10    # 밀리초 단위, 디스크별, 10초

잠금 경쟁 분석 (lockstat)

# lockstat 활성화 (CONFIG_LOCK_STAT 필요)
echo 1 > /proc/sys/kernel/lock_stat
# 워크로드 실행
cat /proc/lock_stat | head -40

# perf lock으로 분석
perf lock record -- sleep 10
perf lock report
# contention 시간이 긴 잠금을 우선 최적화

# lock contention 추적 (BPF)
bpftrace -e 'tracepoint:lock:contention_begin {
    @[kstack] = count();
}'

메모리 프로파일링

# Slab 사용량 분석
slabtop -o -s c    # 캐시 크기순 정렬

# 페이지 할당 추적
echo 1 > /sys/kernel/tracing/events/kmem/mm_page_alloc/enable
cat /sys/kernel/tracing/trace_pipe

# NUMA 메모리 배치 확인
numastat -p $(pidof myapp)
numactl --hardware

# 주요 메모리 튜닝 파라미터
# vm.min_free_kbytes - 비상 메모리 예약 (OOM 방지)
# vm.zone_reclaim_mode - NUMA 존 회수 정책
# vm.vfs_cache_pressure - dentry/inode 캐시 회수 압력

스케줄러 튜닝

파라미터기본값설명
sched_latency_ns6ms (6000000)CFS 스케줄링 주기
sched_min_granularity_ns0.75ms태스크 최소 실행 시간
sched_wakeup_granularity_ns1ms선점 결정 임계값
sched_migration_cost_ns0.5msCPU 마이그레이션 비용 추정
sched_nr_migrate32로드밸런싱 시 이동할 최대 태스크
# 실시간 워크로드 최적화
chrt -f 80 ./realtime_app    # SCHED_FIFO, 우선순위 80

# CPU 고정 (CPU affinity)
taskset -c 2,3 ./app          # CPU 2,3에 고정

# cgroup v2로 CPU 대역폭 제한
echo "100000 1000000" > /sys/fs/cgroup/mygroup/cpu.max  # 10%

Linux 6.6+에서는 EEVDF (Earliest Eligible Virtual Deadline First) 스케줄러가 CFS를 대체합니다. sched_latency_ns 등의 기존 파라미터 대신 deadline 기반 공정성을 제공합니다.