리눅스 free 명령에서 free가 거의 0일 때: buff/cache와 available 읽는 법

free 명령의 free 칸이 작다고 메모리가 부족한 것은 아닙니다. /proc/meminfo와 커널 소스로 buff/cache, available, used의 뜻을 확인하고, 캐시를 습관적으로 비우면 성능에 해로울 수 있는 이유를 정리했습니다.

개발운영체제리눅스

서버에서 free -h를 실행하면 free 칸은 아주 작고 buff/cache 칸은 큰 경우가 많습니다. 이 숫자만으로 메모리가 부족하다고 판단할 수는 없습니다. 새 프로그램에 내줄 수 있는 메모리를 커널이 추정한 값은 available 칸에 따로 있습니다.

각 칸은 /proc/meminfo에서 온다

free는 procps-ng에 들어 있는 도구입니다. 메모리를 직접 세지 않고, 커널이 내보내는 /proc/meminfo를 읽어 보여 줍니다. procps-ng 4.x의 free(1) 매뉴얼에 적힌 대응 관계는 다음과 같습니다.

free 칸 /proc/meminfo 항목 뜻
total MemTotal 쓸 수 있는 전체 RAM
free MemFree 어디에도 쓰이지 않는 메모리
shared Shmem 주로 tmpfs와 공유 메모리
buff/cache Buffers + Cached + SReclaimable 커널 버퍼, 페이지 캐시, 회수 가능한 slab
available MemAvailable 스와프 없이 새 프로그램에 줄 수 있는 양의 추정치
used total − available 쓰이고 있거나 내줄 수 없는 메모리

free -w를 쓰면 buffers와 cache가 따로 나옵니다. 표에 나온 원래 값을 모두 보려면 다음 명령을 쓰면 됩니다.

grep -E '^(MemTotal|MemFree|MemAvailable|Buffers|Cached|SReclaimable|Shmem):' /proc/meminfo

free가 작은 것은 흔한 일이다

Cached의 대부분은 디스크에서 읽은 파일 데이터를 메모리에 담아 둔 페이지 캐시입니다. 같은 데이터를 다시 읽을 때 저장 장치에서 다시 읽어 오지 않아도 됩니다. 리눅스는 RAM을 이런 파일 페이지 캐시로 쓸 수 있고, 메모리가 모자라면 그중 상당 부분을 회수할 수 있습니다. 그래서 파일을 많이 읽는 서버에서 MemFree가 작은 것은 흔한 일이고, 그것만으로 문제가 있다는 신호는 아닙니다. 반대로 MemFree가 작다는 사실이 시스템이 건강하다는 증거가 되는 것도 아닙니다.

free + cache를 더하면 안 되는 이유

예전에는 free와 cached를 더해 여유 메모리로 보는 방식이 흔했습니다. 커널에 MemAvailable을 추가한 2014년 커밋(Rik van Riel)은 이 계산이 이제 거의 항상 틀린다고 설명합니다. Cached에는 공유 메모리, tmpfs, ramfs처럼 캐시를 비워도 회수할 수 없는 메모리가 들어 있고, 회수 가능한 slab은 빠져 있기 때문입니다. 제대로 추정하려면 커널 내부를 알아야 해서, 커널이 직접 계산해 내보내기로 했습니다. 이 항목은 Linux 3.14부터 있습니다.

available은 어떻게 추정되나

Linux v7.2 소스의 si_mem_available()은 대략 다음 순서로 계산합니다.

  1. 비어 있는 페이지 수에서 커널이 예약해 둔 페이지를 뺍니다.
  2. 파일 페이지 캐시(active와 inactive file LRU)를 더합니다. 다만 그 절반과 모든 zone의 low watermark 합 가운데 작은 쪽은 남겨 둬야 한다고 가정하고 뺍니다.
  3. 회수 가능한 slab과 그 밖의 회수 가능한 커널 메모리를 더하고, 2번과 같은 방식으로 일부를 뺍니다.
  4. 결과가 음수이면 0으로 둡니다.

이 계산은 휴리스틱이고, 커널 버전에 따라 바뀔 수 있습니다. 결과는 추정치일 뿐 보장된 값이 아닙니다.

used 값은 procps 버전마다 다르다

procps-ng 3.3.16은 used를 total − free − buffers − (Cached + SReclaimable)로 계산했고, 이 값이 음수이면 total − free를 썼습니다. procps-ng 4.0.1부터는 total − available로 바뀌었습니다. 그래서 메모리 상태가 같아도 procps 버전에 따라 used 숫자가 다르게 나올 수 있습니다. 여러 시스템의 used를 비교하기 전에 free -V로 버전을 확인하세요.

drop_caches는 해결책이 아니다

/proc/sys/vm/drop_caches에 3을 쓰면 깨끗한 페이지 캐시와 dentry, inode 같은 회수 가능한 slab 객체가 버려집니다. 그 결과 free 칸이 커질 수 있습니다. 하지만 커널 문서는 이 파일이 캐시 증가를 제어하는 수단이 아니라고 설명합니다. 커널은 메모리가 필요할 때 이 객체들을 스스로 회수합니다. 버려진 캐시가 다시 필요하면 해당 데이터와 객체를 다시 읽거나 재구성해야 하므로 I/O와 CPU 비용이 생길 수 있습니다. 그래서 문서는 테스트나 디버깅 환경 밖에서는 쓰지 말라고 권합니다. 아직 디스크에 쓰지 않은 더티 객체는 이 방법으로 해제되지도 않습니다.

정리

메모리 여유를 처음 확인할 때는 free보다 available이 더 알맞습니다. 다만 한 번의 값이나 감소 추세만으로 메모리 부족을 확정할 수는 없습니다.

운영체제 숫자가 예상과 다르게 보이는 다른 예로 파일을 지웠는데 디스크 공간이 그대로인 이유도 참고할 수 있습니다.

블로그로