IT·리눅스/리눅스

리눅스 메모리 - RSS, VSZ, Shared 실제로 얼마를 쓰는 걸까

jmineekim 2026. 7. 6. 10:00

운영 서버에서 ps aux의 RSS 컬럼을 다 더해봤더니 실제 물리 메모리보다 큰 숫자가 나와서 한참 멘붕한 적이 있어요. "이게 어떻게 가능하지, 프로세스들이 총 메모리를 초과했으면 죽었어야 하잖아?" 알고 보니 이 착시는 아주 정상적인 현상이었습니다. 원인은 공유 메모리(shared page)를 각 프로세스가 중복 카운트하기 때문이에요. 오늘은 VSZ·RSS·Shared·PSS·USS가 각각 뭐고, 진짜 프로세스가 얼마의 메모리를 쓰는지 어떻게 보는지 정리해볼게요.

개념 / 원리

리눅스 프로세스 메모리 지표는 사실 여러 종류가 있고, 각각 다른 질문에 답합니다.

지표 의미 언제 보나
VSZ 가상 주소 공간 크기 프로세스가 "예약"한 총 크기. 실제 사용량 아님
RSS 지금 물리 메모리에 올라와 있는 페이지 개별 프로세스가 느끼는 사용량
Shared 다른 프로세스와 공유 중인 페이지 라이브러리·mmap 파일 등
PSS RSS 중 공유 페이지를 프로세스 수로 나눈 값 시스템 전체 합산 시 정확
USS 그 프로세스만 쓰는 페이지 (RSS - Shared) 이 프로세스를 죽이면 회수될 양

여기서 헷갈리기 쉬운 게 RSS는 shared 페이지를 그대로 다 포함한다는 점이에요. 예를 들어 libc가 100MB짜리인데 세 프로세스가 공유하면, 세 프로세스 RSS에 각각 100MB가 들어갑니다. 물리 메모리에는 100MB 하나만 있는데도요. 그래서 ps의 RSS 총합은 항상 실제 사용량보다 큽니다.

정확한 총합을 보려면 PSS를 봐야 해요. 공유 페이지를 사용 중인 프로세스 수로 균등 배분하기 때문에, 모든 프로세스의 PSS를 다 더하면 실제 물리 메모리 사용량과 맞아떨어집니다.

내가 이 프로세스만 죽였을 때 얼마가 회수될지 궁금하다면 USS를 봅니다. shared는 다른 프로세스가 여전히 쓰니 회수 안 되고, 진짜 그 프로세스 전용인 부분만 반환되거든요.

실전 예제

기본은 ps 입니다.

# RSS와 VSZ 기준 상위 프로세스
ps -eo pid,user,rss,vsz,comm --sort=-rss | head

한 프로세스의 메모리 맵을 자세히 보려면 pmap -X.

pmap -X <PID> | tail -1
# Address Perm Offset Device Inode Size Rss Pss ...
# Total:                              524288 210432 118920 ...

Size가 VSZ, Rss가 RSS, Pss가 PSS입니다.

시스템 전체를 PSS·USS로 정렬해서 보고 싶다면 smem이 편해요.

sudo apt install smem   # 없으면 설치
smem -tk -s pss         # PSS 기준 정렬, 사람이 읽는 단위
#   PID User    Command                     Swap    USS    PSS    RSS
#  1234 postgres postgres: writer            0    150M   180M   420M

가장 정확한 원본은 /proc/PID/smaps에 다 들어있습니다.

grep -E '^(Rss|Pss|Shared|Private)' /proc/<PID>/smaps | \
  awk '{s[$1]+=$2} END{for(k in s) print k, s[k]" kB"}'

Shared_Clean·Shared_Dirty·Private_Clean·Private_Dirty로 나눠서 나오는데, USS는 대략 Private_Clean + Private_Dirty입니다.

주의할 점

첫째, RSS 합계로 시스템 메모리 계산하지 마세요. shared가 중복 카운트돼 실제보다 훨씬 커집니다. 시스템 총합은 PSS로 보고, 시스템 관점 사용량은 free -hused 값을 보세요.

둘째, VSZ 크다고 걱정할 필요 없어요. JVM이나 Go 프로세스는 가상 주소를 크게 잡아두고 실제로는 조금씩 사용합니다. VSZ가 30GB로 찍혀도 RSS가 500MB면 실제 물리 메모리는 500MB만 씁니다.

셋째, freeavailable을 보세요. used만 보면 항상 높게 나옵니다. 리눅스는 남는 메모리를 파일 캐시로 다 씁니다(buff/cache). available이 "지금 새 프로세스가 쓸 수 있는 실질 여유"라 이게 오히려 정확해요.

넷째, OOM 킬러 대상은 RSS 큰 놈이 아닙니다. 정확히는 oom_score인데, RSS 외에 실행 시간·oom_score_adj 값도 같이 봅니다. /proc/PID/oom_score로 현재 점수를 확인할 수 있고, 절대 죽으면 안 되는 프로세스는 oom_score_adj를 -1000으로 낮춰두면 돼요.

다섯째, container(Docker/K8s)에선 지표 해석이 또 달라집니다. cgroup 메모리 제한 안에서 파일 캐시도 usage에 포함되니, 컨테이너 메모리 사용량이 항상 제한에 붙어 있는 것처럼 보이는 게 정상이에요. 실제 위험 신호는 memory.pressure나 OOM 이벤트로 봅니다.

마무리

정리하면 세 줄입니다.

  • RSS는 공유 페이지 중복 카운트 문제가 있어 합계로 쓰면 안 되고, 시스템 총합은 PSS·free -h로 본다.
  • 이 프로세스만 죽이면 회수될 양은 USS(Private 페이지), 자세한 원본은 /proc/PID/smaps에 있다.
  • VSZ 크기, used 높음은 문제 신호가 아니고, 진짜 여유는 available, 진짜 위험은 OOM 이벤트로 판단한다.
반응형