LabHub

블로그

htop와 top 완벽 해부 — 모든 숫자를 읽는 법

한국어English日本語中文

들어가며 — 숫자의 홍수

리눅스 서버에서 htop이나 top을 처음 열면 숫자와 색깔의 홍수에 압도됩니다. 대부분은 CPU와 메모리 퍼센트만 대충 보고 나머지는 무시하지만, 그 숫자 하나하나에는 시스템의 상태를 진단하는 데 필요한 정보가 담겨 있습니다. 최근 해커뉴스(Hacker News) 상단에 다시 오른 페테리스 니키포로프스(Pēteris Ņikiforovs)의 명문 해설 "Explanation of everything you can see in htop"이 이 주제를 다시 조명한 것을 계기로, 이 글에서는 그 필드들을 하나씩 뜯어보겠습니다.

프로세스 열 읽기

프로세스 목록의 각 열이 무엇을 뜻하는지부터 봅시다.

VIRT, RES, SHR — 메모리 세 값의 함정

메모리 열은 가장 자주 오해되는 부분입니다. 세 값의 의미가 완전히 다릅니다.

여기서 중요한 실무 교훈이 하나 나옵니다. 메모리를 많이 먹는 프로세스를 찾을 때는 VIRT가 아니라 RES 기준으로 정렬해야 한다는 것입니다. VIRT로 정렬하면 실제로는 메모리를 별로 안 쓰는데 주소 공간만 크게 잡은 프로세스가 맨 위에 올라와 오판하기 쉽습니다.

프로세스 상태 문자

S 열에는 한 글자로 된 프로세스 상태가 표시됩니다. 각 문자의 의미는 다음과 같습니다.

로드 애버리지 — CPU 사용률과 다르다

가장 널리 오해되는 지표가 로드 애버리지(load average) 입니다. 흔히 "CPU 사용률"과 같다고 생각하지만 그렇지 않습니다.

첫째, 로드 애버리지는 단순 평균이 아니라 지수 감쇠 이동 평균입니다. 1분, 5분, 15분 세 개의 값이 표시되며, 최근 값에 더 큰 가중치를 둡니다. 1분 값은 대략 지난 1분의 부하를 63%, 그 이전을 37% 정도로 섞은 값입니다.

둘째, 그리고 더 중요한 점 — 로드는 실행 중인(R) 프로세스뿐 아니라 인터럽트 불가능한 수면(D) 상태의 프로세스도 함께 셉니다. 이 때문에 로드가 높다고 반드시 CPU가 바쁜 것은 아닙니다. 디스크나 네트워크 입출력을 기다리는 프로세스가 많아도 로드는 치솟습니다.

셋째, 로드는 코어 수를 기준으로 해석해야 합니다. N개의 코어를 가진 머신에서 로드가 N이면 대략 100% 활용 상태입니다. 코어가 4개인데 로드가 4라면 포화 상태이고, 코어가 8개인데 로드가 4라면 절반만 쓰이는 셈입니다.

이 세 가지를 종합하면 강력한 진단 규칙이 나옵니다. 로드는 높은데 %CPU는 낮다면, 십중팔구 입출력 대기(I/O wait) 입니다. 이때는 D 상태의 프로세스를 찾아보는 것이 문제 해결의 출발점입니다.

미터의 색깔

htop 상단의 막대 미터도 색으로 정보를 전합니다.

여기서 버퍼와 캐시를 "쓰이는 메모리"로 착각하지 않는 것이 중요합니다. 버퍼와 캐시는 커널이 성능을 위해 잠시 빌려 쓰는 영역이며, 애플리케이션이 메모리를 필요로 하면 즉시 반납됩니다. 그래서 실제로 주목해야 할 값은 "used"가 아니라 가용 메모리(available) 입니다. 리눅스에서 "메모리가 거의 다 찼다"는 화면이 대개 문제가 아닌 이유가 이것입니다. 캐시로 채워진 메모리는 필요할 때 비워질 수 있는, 사실상 여유 메모리입니다.

좀비 프로세스의 정체

좀비(Z) 프로세스는 자주 오해됩니다. 몇 가지 사실을 정리하겠습니다.

좀비는 이미 죽은 프로세스입니다. 실행을 마쳤지만, 부모 프로세스가 그 종료 상태를 아직 거둬가지(reap) 않아 프로세스 테이블에 항목만 남아 있는 상태입니다. 그래서 좀비는 메모리를 전혀 소비하지 않습니다. 오직 프로세스 테이블의 슬롯 하나만 차지할 뿐입니다.

또한 좀비는 죽일 수 없습니다. 프로세스를 종료시키려면 시그널을 보내야 하는데, 시그널은 살아 있는 프로세스만 받을 수 있습니다. 이미 죽은 좀비에게 kill -9를 보내도 소용이 없습니다. 좀비가 사라지는 유일한 길은 부모가 그것을 거둬가는 것입니다. 만약 부모가 먼저 죽으면, 좀비는 init(PID 1)에게 입양되고 init이 대신 거둬갑니다.

즉 좀비가 몇 개 보인다고 당황할 필요는 없습니다. 좀비가 계속 쌓인다면 그것은 좀비 자체가 문제라기보다, 자식을 제대로 거둬가지 않는 부모 프로세스의 버그를 가리키는 신호입니다.

카피 온 라이트와 RES의 착시

한 가지 미묘한 현상을 덧붙이겠습니다. 프로세스가 fork로 자식을 만들면, 리눅스는 카피 온 라이트(copy-on-write) 를 씁니다. 부모와 자식이 같은 물리 메모리 페이지를 공유하다가, 어느 쪽이 쓰기를 할 때에만 그 페이지를 복제합니다.

이 때문에 htop에서 부모와 자식이 각각 전체 RES를 통째로 표시할 수 있습니다. 겉보기에는 메모리를 두 배로 쓰는 것 같지만, 실제 물리 메모리는 공유되고 있어 합계가 그만큼 크지 않습니다. 프로세스를 많이 fork하는 프로그램의 메모리를 볼 때 이 착시를 염두에 두어야 합니다.

실전 진단 레시피

지금까지의 내용을 실제 문제 해결에 적용하면 다음과 같습니다.

이 도구들을 브라우저에서 직접 만져보고 싶다면 이 사이트의 리눅스 터미널이나 웹 터미널을, 커널 파라미터가 이런 동작에 어떻게 관여하는지 살펴보고 싶다면 커널 파라미터 탐색기를 함께 열어보면 좋습니다.

마치며

htop과 top의 숫자들은 처음엔 암호처럼 보이지만, 각 필드의 의미를 알고 나면 시스템의 상태를 읽는 강력한 진단 도구가 됩니다. 특히 VIRT와 RES의 차이, 로드가 입출력 대기를 포함한다는 사실, 캐시가 사실상 여유 메모리라는 점 — 이 세 가지만 제대로 이해해도 서버 문제 진단의 절반은 해결됩니다.

참고 자료

댓글

아직 댓글이 없습니다.

로그인하면 댓글을 쓸 수 있습니다