Linux에서 메모리 여유를 빠르게 판단할 때는 free 열보다 available 열을 먼저 본다. 파일 캐시와 회수 가능한 커널 캐시는 필요할 때 애플리케이션에 돌려줄 수 있기 때문이다. Slab이 크다면 SReclaimable과 SUnreclaim을 나누고, 그다음 slabtop에서 dentry 같은 개별 커널 객체를 확인한다.
예전 글에서는 SReclaimable을 “주로 dentry/inode cache”라고 묶고 /proc/meminfo만으로 dentry 크기를 확인할 수 있는 것처럼 적었다. 정확하지 않았다. SReclaimable은 여러 회수 가능한 slab 캐시의 합이고, dentry 하나의 크기는 slabtop이나 /proc/slabinfo에서 따로 봐야 한다.
free -h에서 먼저 볼 값
free -h
대표 출력 형식은 다음과 같다.
total used free shared buff/cache available
Mem: 31Gi 12Gi 1.2Gi 900Mi 18Gi 17Gi
Swap: 8.0Gi 512Mi 7.5Gi
| 열 | 의미 | 해석할 때 주의할 점 |
|---|---|---|
total |
커널이 사용할 수 있는 전체 메모리 | 장착된 RAM과 조금 다를 수 있다. |
used |
사용 중으로 계산된 메모리 | procps 버전에 따라 계산식이 달라질 수 있다. |
free |
아무 용도로도 쓰이지 않는 메모리 | 작다는 이유만으로 부족하다고 판단하지 않는다. |
buff/cache |
버퍼와 페이지 캐시, 일부 회수 가능 slab | 필요하면 상당 부분 회수할 수 있다. |
available |
스왑 없이 새 작업에 쓸 수 있다고 추정한 메모리 | 현재 여유를 볼 때 가장 실용적인 첫 지표다. |
Linux 커널은 MemAvailable을 MemFree, 파일 LRU, SReclaimable, zone low watermark 등을 바탕으로 추정한다. 회수 가능하다고 표시된 메모리도 전부 즉시 회수할 수 있는 것은 아니라는 점까지 계산에 반영한다.
macOS의 명령과 비교하려면 macOS에서 free 대신 메모리 확인하는 법을 참고할 수 있다.
page cache와 slab cache는 무엇이 다른가
둘 다 성능을 위해 메모리를 쓰지만 저장하는 대상이 다르다.
- page cache는 디스크에서 읽은 파일 내용을 메모리에 보관한다.
- slab cache는 dentry, inode, 네트워크 버퍼 등 커널 내부 객체를 보관한다.
- dentry cache는 경로 이름을 inode와 연결하는 VFS 객체를 재사용해 경로 탐색 비용을 줄인다.
free의 buff/cache는 이 메모리들을 한눈에 보는 요약이다. 정확한 원인을 찾으려면 /proc/meminfo와 slab별 통계로 내려가야 한다.
/proc/meminfo에서 slab을 나눠 보기
grep -E '^(MemAvailable|Buffers|Cached|Slab|SReclaimable|SUnreclaim):' /proc/meminfo
MemAvailable: 17823456 kB
Buffers: 123456 kB
Cached: 10485760 kB
Slab: 2097152 kB
SReclaimable: 1572864 kB
SUnreclaim: 524288 kB
Slab: 커널 내부 데이터 구조 캐시의 전체 크기SReclaimable: 메모리 압박이 생기면 커널이 회수를 시도할 수 있는 부분SUnreclaim: 메모리 압박에도 회수할 수 없는 부분
중요한 관계는 다음과 같다.
Slab ≈ SReclaimable + SUnreclaim
SReclaimable이 크다고 곧바로 누수는 아니다. 파일을 많이 탐색했거나 컨테이너 이미지처럼 작은 파일을 대량으로 다룬 뒤 dentry와 inode 캐시가 커질 수 있다. 반대로 SUnreclaim이 계속 증가하고 메모리 압박도 함께 커진다면 커널 객체 누수나 특정 서브시스템을 의심할 근거가 된다.
dentry가 실제로 큰지 확인하기
요약이 아니라 개별 slab 캐시를 보려면 slabtop을 사용한다.
sudo slabtop -o
-o는 한 번 출력하고 종료한다. 출력에서 dentry, inode_cache, 파일시스템별 inode 캐시와 kmalloc-* 항목의 객체 수와 캐시 크기를 비교한다. 권한 정책이나 컨테이너 환경에 따라 /proc/slabinfo 접근이 제한될 수 있다.
dentry만 빠르게 찾는 예시는 다음과 같다.
sudo awk '$1 == "dentry" { print }' /proc/slabinfo
SReclaimable 전체를 dentry 크기로 부르면 안 되는 이유가 여기 있다. 이 값에는 inode와 다른 회수 가능한 커널 캐시도 함께 들어간다.
숫자가 클 때의 진단 순서
free -h에서available과 swap 사용량을 본다.vmstat 1로si·so가 계속 발생하는지 확인한다./proc/meminfo에서 page cache와 slab,SReclaimable·SUnreclaim을 나눈다.- slab이 원인이라면
slabtop -o에서 큰 캐시를 찾는다. - 애플리케이션 메모리인지 커널 메모리인지 구분한 뒤 다음 도구를 고른다.
운영 중인 서버에서는 캐시를 강제로 비우기 전에 이 순서를 거치는 편이 안전하다. drop_caches는 원인을 해결하지 않고 성능에 필요한 캐시까지 버릴 수 있다. 전체 분석 흐름은 실제 메모리 문제를 분석하는 순서, 애플리케이션 쪽 할당 구조는 malloc이 내부에서 메모리를 관리하는 방식으로 이어서 볼 수 있다.
참고 자료
'배움과 성장 > 시스템·성능' 카테고리의 다른 글
| Linux man 페이지 섹션과 syscall 추적: man 1·2·3·5·7·8 (5) | 2024.12.06 |
|---|---|
| JIT 컴파일과 가상 머신: bytecode·ISA·profiling·deoptimization 구분 (0) | 2024.12.05 |
| CPU와 메모리 차이: 프로그램이 실행될 때 실제로 일어나는 일 (2) | 2024.09.23 |
| Linux CPU 스케줄러 동작: task·run queue·dispatcher 구분하기 (6) | 2024.09.22 |
| Linux 시스템 콜이란: 사용자 모드·커널 모드와 strace 추적 (4) | 2024.09.21 |
댓글