Load Average가 무엇인지, 어떤 방식을 통해 계산되는지 정리한 문서입니다.
1편은 개념을 설명하고 이어서 2편에 실습을 통해 정리합니다.
리눅스 시스템에서 CPU와 디스크 I/O가 얼마나 바쁜지 나타내는 지표 중 하나입니다.
uptime이나 /proc/loadavg 를 살펴보면 세 개의 숫자가 나옵니다.

각각 최근 1분, 5분, 15분에 대한 값입니다.
흔히 “부하율”로 읽지만, 정확히는 시스템이 처리해야 할 작업이 평균적으로 몇 개나 쌓여 있었는가를 나타내는 수치입니다.
백분율(%)이 아니라 개수(태스크 수) 라는 점이 핵심입니다.
직관적으로 봤을 때, CPU가 1개인 시스템에서
그래서 load average는 "얼마나 바쁜가(%)"가 아니라 "얼마나 밀려 있는가(대기 행렬의 길이)" 에 가깝습니다.
이 차이가 뒤에 나올 두 가지 오해의 출발점입니다.
가장 흔한 오해입니다.
Load average를 CPU 사용률과 같다고 생각하면, 앞에서 본 "CPU는 노는데 load는 높은" 상황을 설명할 수 없습니다.
리눅스가 load에 반영하는 작업은 두 종류입니다.
즉 커널이 세는 값은 대략 다음과 같습니다.
active = nr_running(R) + nr_uninterruptible(D)
바로 이 D 상태 포함이 리눅스 load average의 결정적 특징입니다.
전통적인 Unix는 실행 가능한(R) 태스크만 셌지만, 리눅스는 1993년 패치 이후에 I/O 대기(D)까지 포함하도록 바뀌었습니다.
그 결과 리눅스의 load average는 "CPU 수요"가 아니라 "시스템 전체 수요(CPU + I/O 대기)" 를 의미하게 되었습니다.
그래서 이런 일이 생깁니다.
load가 높다 = CPU가 바쁘다가 무조건적으로는 아닙니다.
load는 CPU 경합과 I/O 대기를 한 숫자에 섞어 담습니다.
이 점은 뒤에서 다시 문제로 돌아옵니다.
1분 평균이라고 하니 최근 60초 동안의 값을 산술평균한다고 생각하기 쉽지만, 아닙니다.
리눅스는 지수 가중 이동 평균(EWMA, Exponentially Weighted Moving Average) 으로 계산합니다.
EWMA (지수 가중 이동 평균)
최근 값에 가장 큰 가중치를 주고, 오래된 값일수록 가중치를 지수적으로 줄여 나가는 평균입니다.
최근 N개를 똑같은 비중으로 평균 내는 단순이동평균(SMA)과 달리, 새 값에 민감하게 반응하면서도 과거를 완전히 잊지는 않습니다.
게다가 이전 평균 하나만 기억하면 갱신되므로, 지난 데이터를 쌓아둘 필요가 없습니다.
동작은 이렇습니다.
핵심 갱신식은 다음과 같습니다. 여기서 exp가 "과거 값을 얼마나 유지할지"를 정하는 감쇠 상수입니다.
새 load = (기존 load × exp) + (현재 active × (1 - exp))
과거 값에 exp만큼 가중치를 주고, 새 관측값에 나머지를 주는 전형적인 EWMA입니다.
exp가 1에 가까울수록 과거를 오래 기억합니다(= 값이 천천히 변합니다).
커널은 부동소수점 없이 계산한다
이 코드 경로에서는 부동소수점 연산을 쓰지 않기 때문에, 커널은 고정소수점(fixed-point) 으로 처리합니다.
실제 코드는 대략 이렇습니다.

5초 샘플 + 시정수 1/5/15분을 커널이 직접 명시

위 개념식과 일치

실제 구현 코드 (고정소수점)

부동소수점 없이 계산
(커널엔 부동소수점이 없어서 정수로 소수를 흉내낸다는 뜻)
11비트 소수부를 곱하면 22비트가 되고, 그래서 정수 10비트 + 소수 11비트 정밀도. → FSHIFT=11
"With 2-second counting freq, the EXP_n values would be 1981, 2034, 2043"
만약 2초마다 셌다면 상수가 1981/2034/2043이 됐을 것. → EXP 값이 샘플링 주기(5초)에 종속임
출처: https://elixir.bootlin.com/linux/v7.1.8/source/include/linux/sched/loadavg.h
15분 상수가 1분 상수보다 2048(=1.0)에 가깝다는 점에 주목하세요.
과거를 더 오래 기억하기 때문에 값이 그만큼 천천히 움직입니다.
그래서 1분은 구간이 아니라 시간상수입니다.
여기서 가장 중요한 결론이 나옵니다. "1분/5분/15분"은 평균을 낸 구간이 아니라, 지수 감쇠의 시간상수(time constant) 입니다.
Load Average는 익숙하지만 오해하기 쉬운 지표입니다.
이번 글에서 정리한 핵심은 세 가지입니다.
한 줄로 줄이면, Load Average는 "시스템이 감당해야 할 일의 양(CPU + I/O 수요)을 완만하게 평활한 추정치" 입니다.
그런데 여기서 자연스러운 의문이 남습니다.
load가 R과 D를 한 숫자에 섞어 담는다면, 실제로 서버 load가 치솟았을 때 그것이 CPU 문제인지 I/O 문제인지 어떻게 가려낼 수 있을까요?
다음 글에서는 CPU-bound와 I/O-bound 상황을 직접 재현해 load가 어떻게 달라지는지 보고, vmstat로 그 부하의 정체를 진단하는 방법을 실습으로 다뤄보겠습니다.
감사합니다.
정택준
Team: https://nangman.cloud/ko
E-mail: taekjunnnn@nangman.cloud