RHEL 고급 #3 성능 분석 — sar, top/htop, iostat, vmstat, perf

8 분 소요

#2 커널 튜닝에서 워크로드에 맞게 튜닝하는 도구를 봤습니다. 이번 글은 그 반대 방향입니다. 머신이 이미 돌고 있는데 느려졌을 때, 어디부터 봐야 할지를 정합니다. top, vmstat, iostat, sar, perf 다섯 도구를 어떤 신호 앞에서 꺼내드는지, 그리고 USE (Utilization , Saturation , Errors) 라는 단순한 체크리스트로 묶어 한 사이클로 다루겠습니다.

RHEL 고급 시리즈에서 이번 글의 위치:

네 자원과 USE 체크리스트 #

성능 문제는 결국 네 자원 중 하나에서 새는 것입니다.

자원무엇을 보나
CPU사용률, run queue 길이, context switch
Memory사용량, swap 활동, page fault
Disk I/OIOPS, throughput, await(응답 시간), util%
Networkbandwidth, packet rate, error/drop

각각에 대해 같은 세 신호를 봅니다 — Brendan Gregg의 USE 방법론.

  • Utilization — 자원이 얼마나 쓰이고 있나 (사용률 %)
  • Saturation — 자원이 일을 다 못 처리해 큐에 쌓이나
  • Errors — 에러가 발생하나

CPU가 바빠 보여도 (U 높음) 큐에 쌓이지 않고 (S 낮음) 에러도 없으면 (E 0) 정상 운영입니다. 반대로 CPU 사용률이 50%인데 run queue가 30이면, 사용률은 평범해 보여도 saturation에서 빨간불이 켜진 상태입니다. 항상 U/S/E 셋을 같이 봐야 진단이 정확해집니다.

첫 시야 — top / htop #

가장 빨리 손에 잡히는 도구입니다. 머신에 들어간 직후 먼저 띄우는 게 표준 절차입니다.

top 기본
$ top
top - 14:23:15 up 12 days,  4:11,  2 users,  load average: 1.52, 0.98, 0.65
Tasks: 312 total,   2 running, 310 sleeping,   0 stopped,   0 zombie
%Cpu(s):  8.3 us,  2.1 sy,  0.0 ni, 88.5 id,  0.7 wa,  0.3 hi,  0.1 si,  0.0 st
MiB Mem :  15891.2 total,   3421.5 free,   8123.4 used,   4346.3 buff/cache
MiB Swap:   2048.0 total,   2048.0 free,      0.0 used.   7234.8 avail Mem

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
 1234 postgres  20   0 1234567  98765  43210 R  45.2   0.6   3:12.45 postgres
 ...

첫 줄 — load average #

load average: 1.52, 0.98, 0.65의 세 숫자는 지난 1분 / 5분 / 15분 동안 평균적으로 실행 가능 상태였던 프로세스 수 입니다.

  • CPU 코어 수(예: 4)와 비교 — 4를 넘으면 CPU가 모자란다는 신호
  • 1/5/15 추세 — 1분 > 15분이면 부하가 올라가는 중, 반대면 가라앉는 중
  • 리눅스의 load average는 R 상태 + D 상태 (uninterruptible sleep, 보통 디스크 IO 대기) 둘 다 포함. 그래서 디스크가 늦으면 CPU가 한가해도 load가 치솟습니다.

CPU 라인 — %Cpu(s) #

필드의미
us사용자 공간 CPU
sy커널 공간 CPU
ninice 값 변경된 프로세스
ididle
waI/O wait — CPU는 한가한데 IO를 기다리는 비율
hi / sihardirq / softirq
ststeal — 가상화 환경에서 하이퍼바이저가 가져간 시간

wa가 높으면 디스크/네트워크 IO가 병목, st가 높으면 (클라우드 인스턴스에서) 노이지 네이버 영향이 의심.

htop — 더 읽기 쉬운 top #

설치와 사용
$ sudo dnf install -y htop
$ htop
  • 코어별 사용률 막대 그래프
  • 프로세스 트리 모드 (F5)
  • 검색 (F3), 필터 (F4), kill (F9), nice 변경 (F7/F8)
  • 마우스 클릭으로 정렬

운영에서는 top이 항상 있다고 가정해야 하지만 (기본 설치), 손에 잡히는 첫 도구로는 htop이 훨씬 빠릅니다.

자주 쓰는 top 단축키 #

동작
1코어별로 펼쳐 보기
M메모리 사용량 순 정렬
PCPU 사용량 순 정렬
T누적 시간 순 정렬
c전체 명령행 보기
H스레드 단위로 펼쳐 보기
kkill 프로세스
q종료

vmstat — CPU,메모리,IO 한 화면 #

vmstat 1초 간격
$ vmstat 1
procs -----------memory---------- ---swap-- -----io---- -system-- -------cpu-------
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 1  0      0 421888  35420 1234560    0    0     8    23  150  280  3  1 95  1  0
 0  0      0 421872  35420 1234560    0    0     0     0  120  240  1  0 99  0  0
 2  1      0 421860  35420 1234560    0    0     0   512  185  320  8  2 88  2  0
컬럼의미
rrun queue — 실행 대기 중인 프로세스 수 (CPU saturation)
bblock — uninterruptible sleep 중인 프로세스 수 (보통 IO 대기)
si / soswap in/out (KB/s) — 0이 아니면 메모리 부족 의심
bi / boblock in/out (KB/s) — 디스크 읽기/쓰기
in / cs초당 인터럽트 / context switch
us / sy / id / wa / sttop과 동일

무엇을 봐야 하나 #

  • r > CPU 코어 수 — CPU saturation. 줄을 서서 기다리는 프로세스가 있음
  • si/so > 0 — 페이지가 스왑으로 오가는 중. 메모리 saturation
  • wa가 높고 b가 0보다 큼 — 디스크 IO 병목
  • cs가 비정상적으로 높음 — context switch 폭주 (스레드 너무 많음, 락 경합 등)

vmstat 1 한 줄로 네 자원의 상태를 동시에 본다 — 진단의 두 번째 카드입니다.

iostat — 디스크 자세히 #

sysstat 패키지 안에 들어 있습니다.

설치와 기본
$ sudo dnf install -y sysstat
$ iostat -xz 1
Linux 5.14.0-... (host)   04/28/2026   _x86_64_   (4 CPU)

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           5.32    0.00    1.84    2.41    0.00   90.43

Device            r/s     w/s     rkB/s     wkB/s   rrqm/s   wrqm/s  %rrqm  %wrqm  r_await  w_await aqu-sz  rareq-sz  wareq-sz  svctm  %util
nvme0n1         12.34   45.67    234.56    812.34     0.00     2.11   0.00   4.42     0.32     1.45   0.07     19.01     17.79   0.21   1.23
nvme0n1p1        0.00    0.01      0.02      0.05     0.00     0.00   0.00   0.00     0.10     0.50   0.00      8.00      8.00   0.05   0.00

-x 확장 통계, -z 활동 없는 장치 숨김, 1 초 간격.

컬럼의미
r/s / w/s초당 read/write 요청 수 (IOPS)
rkB/s / wkB/s초당 read/write 처리량
r_await / w_await평균 응답 시간 (밀리초) — 큐 대기 + 서비스 시간
aqu-sz평균 큐 길이 (saturation)
%util디스크가 IO 처리에 쓴 시간 비율

무엇을 봐야 하나 #

  • %util 100% 가까움 + aqu-sz가 큼 — 디스크가 포화 상태. SSD라면 IOPS 한계 부근일 수 있음
  • await가 비정상적으로 큼 (HDD: 20ms+, SSD: 5ms+) — 응답 시간 문제
  • rkB/s + wkB/s가 디스크 사양에 가까움 — bandwidth saturation

%util만 보면 오해할 수 있습니다. 최신 NVMe는 병렬 처리가 가능해서 %util 100%가 곧 saturation은 아닙니다. aqu-szawait를 같이 봐야 정확합니다.

CPU와 같이 보기 #

CPU + 디스크 한 번에
$ iostat -xz 1

iostat은 첫 단락에 CPU 평균까지 보여줍니다. CPU %iowait가 높고 디스크 %util도 높으면 디스크 병목이 명확해지는 식.

sar — 시간 흐름 #

top/vmstat/iostat은 지금 이 순간을 봅니다. 어제 새벽 3시에 무슨 일이 있었는지는 못 잡아냅니다. 그 시간대 데이터를 추적할 수 있는 도구가 sar입니다. sysstat 패키지가 백그라운드에서 매 10분(기본)마다 시스템 통계를 수집해서 /var/log/sa/에 쌓아둡니다.

활성화 — RHEL 9는 보통 자동
$ sudo systemctl enable --now sysstat
$ sudo systemctl status sysstat-collect.timer

시간 단위 조회 #

오늘
$ sar -u
Linux 5.14.0-...   04/28/2026

00:00:01 AM     CPU     %user     %nice   %system   %iowait    %steal     %idle
00:10:01 AM     all      2.34      0.00      0.81      0.12      0.00     96.73
00:20:01 AM     all      3.21      0.00      0.92      0.14      0.00     95.73
...
다른 날 — /var/log/sa/sa<일자>
$ sar -u -f /var/log/sa/sa27   # 27일치

자원별 옵션 #

옵션자원
-uCPU
-r메모리
-S스왑
-bI/O 전체
-d디스크별
-n DEV네트워크 인터페이스
-n EDEV네트워크 에러
-qrun queue, load average
-wcontext switch
-W페이지 swap

시점 한정과 평균 라인 #

9시 ~ 11시 사이만
$ sar -u -s 09:00:00 -e 11:00:00

# 평균만
$ sar -u -A | grep Average

성능 사고가 났을 때 사후 분석의 핵심 도구입니다. 사고 시점에 들어가서 본 게 아니라 사고 이후에 들어가서 보는 용도. top으로는 못 잡아내는 시간대의 행적을 잡아냅니다.

sar 데이터 보존 기간 #

기본값은 28일. /etc/sysconfig/sysstatHISTORY=로 늘립니다.

6개월 보존
$ sudo sed -i 's/^HISTORY=.*/HISTORY=180/' /etc/sysconfig/sysstat

장기 추세 분석이 필요한 운영 머신은 90 ~ 180일로 늘리는 게 표준입니다.

perf — CPU 핫스폿 #

CPU가 바쁜데 어떤 함수에서 시간을 먹는지 알고 싶을 때. 커널 함수까지 포함한 콜스택 단위 프로파일링 도구입니다.

설치
$ sudo dnf install -y perf

30초 동안 시스템 전체 프로파일링 #

시스템 전체
$ sudo perf record -F 99 -ag -- sleep 30
$ sudo perf report
옵션의미
-F 99초당 99회 샘플링 (HZ와 겹치지 않게 99 권장)
-a모든 CPU
-g콜스택 포함
-- sleep 3030초 동안

특정 PID #

프로세스 단위
$ sudo perf record -F 99 -p 1234 -g -- sleep 30
$ sudo perf report

결과 보기 #

perf report는 텍스트 인터페이스. 함수별 CPU 시간 비율을 콜스택과 함께 보여줍니다.

report 예시 (개요)
+   45.32%  postgres   postgres            [.] hash_search_with_hash_value
+   12.45%  postgres   postgres            [.] heap_hot_search_buffer
+    5.21%  postgres   libc-2.34.so        [.] __memcpy_avx_unaligned_erms
...

Flame Graph — 시각화 #

perf report의 텍스트는 깊은 콜스택을 보기 어려운 편입니다. Brendan Gregg의 FlameGraph 도구로 SVG로 변환:

flame graph 만들기
$ sudo perf record -F 99 -ag -- sleep 30
$ sudo perf script > out.perf
$ ./FlameGraph/stackcollapse-perf.pl out.perf > out.folded
$ ./FlameGraph/flamegraph.pl out.folded > flame.svg

브라우저에서 flame.svg를 열면 콜스택의 너비가 그대로 시간 비율이 됩니다. 어디가 뜨거운지 한눈에 보임.

묶어서 한 흐름 #

문제가 들어왔을 때 어떤 순서로 도구를 꺼내드는지 한 사이클로 정리.

진단 흐름
1. top / htop          ← 첫 시야. load avg, CPU/MEM 큰 그림
2. vmstat 1            ← r, b, si/so, wa로 CPU,MEM,IO 한 화면
3. 자원이 보이면 — 그 자원 전용 도구로 깊이
   ├─ CPU의심  → perf record / report
   ├─ MEM의심  → free -h, /proc/meminfo, smem
   ├─ Disk의심 → iostat -xz 1, biotop, iotop
   └─ Net의심  → ss -s, sar -n DEV/EDEV, iftop
4. 시간 흐름 필요 → sar -u/-r/-d/-n DEV (-f /var/log/sa/sa..)
신호첫 도구두 번째 도구
load avg가 코어 수 초과top (r 컬럼이 vmstat에서)perf record
wa가 높음iostat -xz 1iotop 또는 biotop (BCC)
si/so > 0free -h, vmstatsmem, OOM 후보 식별
cs 폭주pidstat -w 1락 경합 의심, perf로
어제 새벽 3시 그래프sar -u -s 03:00 -e 04:00 -f /var/log/sa/saYY같은 시점 다른 자원 sar

흔한 함정 #

  • load average만 보고 CPU 부하라고 단정 — 리눅스 load는 D 상태도 포함. 디스크가 늦으면 CPU가 한가해도 치솟습니다. 항상 vmstatrb를 함께 봐야 합니다.
  • %util만으로 디스크 saturation 판단 — NVMe는 병렬 처리를 지원합니다. aqu-szawait를 함께 봐야 정확합니다.
  • %CPU 합계가 100% 를 넘는 게 이상하다 — 정상. top의 기본 표시는 코어 합산이라 4코어면 최대 400%. 1 키로 코어별 펼쳐 봐야 코어당 사용률이 보입니다.
  • sar 활성화 안 함 — RHEL 9는 자동이지만 일부 minimal 설치에서 빠져 있을 수 있습니다. 사고 후에 활성화해도 그 시점 데이터는 못 가져옵니다. 운영 머신은 미리 켜두기.
  • perf record를 운영 트래픽에 길게 — 샘플링 자체가 약간의 오버헤드. 운영 인스턴스에서는 30초 ~ 1분 단위로 끊어서.
  • top의 메모리 used를 단순 합산 — buff/cache가 used에 포함된 표기 방식. 실제 가용 메모리는 available로 확인해야 합니다. free -havailable 컬럼이 신뢰할 수 있는 값.

기억해 둘 명령 #

작업명령
첫 시야top 또는 htop
CPU/MEM/IO 한 화면vmstat 1
디스크 자세히iostat -xz 1
메모리 진짜 가용free -h
프로세스별 CPU/IOpidstat 1 / pidstat -d 1
시간 흐름 (오늘)sar -u, sar -r, sar -d
시간 흐름 (특정일)sar -u -f /var/log/sa/sa<일>
CPU 프로파일링sudo perf record -F 99 -ag -- sleep 30 && sudo perf report
네트워크 통계ss -s, sar -n DEV 1
컨텍스트 스위치vmstat 1cs, pidstat -w 1

정리 #

  • USE 체크리스트 — Utilization , Saturation , Errors. CPU/MEM/Disk/Network 네 자원에 대해 각각 셋을 본다.
  • 첫 카드는 top/htop — load average와 큰 그림. 그다음 vmstat 1으로 네 자원의 상태를 한 화면에.
  • 자원이 좁혀지면 전용 도구 — Disk는 iostat -xz 1, CPU 핫스폿은 perf record, 메모리는 free -h + smem.
  • 시간 흐름은 sar — 사고 후에 들어가서 보는 용도. 보존 기간을 90 ~ 180 일로 늘려두면 장기 추세 분석에 유용.
  • 신호를 헷갈리지 말 것 — load avg는 D 포함, %util은 NVMe에서 saturation 지표로 부족, top 메모리 used는 buff/cache 포함.

다음 글은 보안 쪽으로 다시 한 번 깊이 들어갑니다. 중급 #1 SELinux 입문에서 본 표준 도구들 너머의 영역 — 정책을 직접 작성하고 audit2allow로 모듈을 만들어 영구 적용 하는 흐름을 다루겠습니다.

X