>_ josetilabs.com
← blog

28 out 2026 · linux, memória, processos · 4 min

Como medir a memória de um processo de verdade?

RSS conta páginas residentes, VSZ conta espaço de endereços, e nenhum dos dois é o que o cgroup cobra. Para saber o custo real de um processo, leia PSS em /proc/PID/smaps_rollup e memory.current no cgroup dele. Top e htop mostram RSS, que conta bibliotecas compartilhadas várias vezes e ignora cache de página.

O erro mais comum ao olhar para um processo é tratar RES do top como “memória usada”. RES é RSS: páginas do processo que estão na RAM neste momento. Ele não diz quem compartilha essas páginas, não conta o cache que o kernel guarda para esse processo, e não diz se o espaço de endereços está só reservado ou de fato ocupado.

O que cada número mede

Métrica Onde ler O que conta Quando olhar
VmSize / VSZ /proc/PID/status ou statm Espaço de endereços mapeado, incluindo o que só foi reservado Só para saber o teto teórico
VmRSS / RSS /proc/PID/status ou statm Páginas residentes na RAM, compartilhadas contadas inteiras para cada processo Visão rápida no top
PSS /proc/PID/smaps_rollup RSS dividido entre os processos que compartilham a página Memória real atribuível
USS soma de Private_* no smaps_rollup Páginas privadas do processo, sem compartilhamento Quanto libera se matar o processo
memory.current /sys/fs/cgroup/…/memory.current RSS + cache + memória de kernel do cgroup inteiro O que o orçamento do contêiner mede

O que o cgroup cobra

O cgroup é a unidade que o kernel usa para cobrar memória de um contêiner ou de um serviço. memory.current inclui o RSS do processo, o cache de página atribuído a esse cgroup e um pouco de memória de kernel. É por isso que um contêiner com limite de 256 MB pode ser morto pelo OOM killer mesmo com RSS de 200 MB: o cache conta.

Se o processo roda no host, sem cgroup próprio, memory.current do cgroup do usuário mistura tudo, e a leitura perde o sentido. Rode o processo isolado, num contêiner ou numa unidade systemd com MemoryMax, para a conta fechar.

Artefato: medir um processo em 30 segundos

O script abaixo mede um PID que você passar ou, sem argumento, cria um filho que aloca 32 MiB e mede ele. Ele lê /proc, smaps_rollup e o cgroup do processo, e imprime os cinco números lado a lado.

bash
#!/usr/bin/env bash
set -euo pipefail

ALLOC_MB="${ALLOC_MB:-32}"
DUR="${DUR:-4}"
PAGINA="$(getconf PAGESIZE 2>/dev/null || echo 4096)"

medir() {
  local pid="$1"
  echo "=== PID $pid ==="
  if [ ! -d "/proc/$pid" ]; then
    echo "processo nao existe"; return 1
  fi
  echo "-- /proc/$pid/status --"
  grep -E '^(Name|VmSize|VmRSS|VmHWM|VmSwap|Threads):' "/proc/$pid/status" || true
  echo "-- /proc/$pid/statm (pages of $PAGINA bytes) --"
  cat "/proc/$pid/statm"
  echo "-- smaps_rollup --"
  grep -E '^(Rss|Pss|Shared_Clean|Private_Clean|Shared_Dirty|Private_Dirty|Anonymous|Swap|Locked):' "/proc/$pid/smaps_rollup" 2>/dev/null || echo "(sem smaps_rollup)"
  echo "-- cgroup --"
  local cg
  cg="$(sed -n 's/^0:://p' /proc/$pid/cgroup 2>/dev/null)"
  echo "cgroup path: ${cg:-?}"
  if [ -n "$cg" ] && [ -f "/sys/fs/cgroup${cg}/memory.current" ]; then
    echo "memory.current: $(cat /sys/fs/cgroup${cg}/memory.current) bytes"
    echo "memory.max:     $(cat /sys/fs/cgroup${cg}/memory.max 2>/dev/null || echo ?)"
    echo "memory.stat rss/cache:"
    grep -E '^(rss|cache|anon|kernel) ' "/sys/fs/cgroup${cg}/memory.stat" 2>/dev/null || true
  fi
  echo "-- ps --"
  ps -o pid,vsz,rss,%mem,comm -p "$pid" 2>/dev/null || true
}

if [ $# -ge 1 ] && [ -n "${1:-}" ]; then
  medir "$1"
  exit 0
fi

echo "Alocando ${ALLOC_MB} MiB num processo filho e medindo..."
(
  x=$(head -c $((ALLOC_MB*1024*1024)) /dev/zero | tr '\0' 'A')
  : "${x:0:1}"
  sleep "$DUR"
) &
child=$!
trap 'kill "$child" 2>/dev/null || true; wait "$child" 2>/dev/null || true' EXIT
sleep 1
medir "$child"
echo
echo "Legenda: VSZ = espaco de enderecos; RSS = paginas residentes; PSS divide compartilhado; cgroup memory.current inclui cache do processo."

Salve como mede-memoria.sh, torne executável com chmod +x mede-memoria.sh.

Como verificar

Rode ALLOC_MB=32 ./mede-memoria.sh. A saída deve ter VmRSS entre 90 e 110 MiB (o bash que segura a string de 32 MiB tem overhead próprio) e memory.current entre 95 e 120 MiB. Se memory.current for maior que VmRSS, a diferença é cache e memória de kernel do cgroup.

Terminal com o script medindo um processo filho: VmRSS 97548 kB e memory.current 105308160 bytes
Saída real do script num contêiner isolado com 256 MB e 0,5 CPU.

Se der errado

Qual usar quando

Se você quer entender por que o limite do contêiner é em cgroup, leia O que são cgroups. Se o problema é descobrir quem está consumindo memória no host, Como ver o que está comendo a memória no Linux. Para limitar um contêiner de propósito, Como limitar memória, log e reinício de um contêiner.

FAQ

RSS e “memória usada” são a mesma coisa? Não. RSS conta páginas residentes, incluindo compartilhadas; não conta cache por processo; não diz se o espaço está reservado ou usado.

Por que VSZ é tão grande? É o espaço de endereços reservado por mmap e malloc. Não é RAM.

PSS ou USS para decidir se mato um processo? USS diz o que libera. PSS é melhor para comparar processos que compartilham bibliotecas.

Top não basta? Top é bom para achar o suspeito. Para cobrar custo, use o cgroup.

Como medir um contêiner inteiro? Leia memory.current do cgroup do contêiner. É a conta que o kernel usa para aplicar o limite.

Fontes

Leia também

// Por e-mail

Os textos publicados aqui também vão por e-mail. O envio ainda não começou: quem deixar o endereço agora entra na primeira lista.

Guardo só o seu e-mail, a data e o registro desta autorização. Sem cookies, sem rastreador e nada compartilhado com terceiros. Detalhes na política de privacidade.