Diagnosticando Load Average Alto: CPU-Bound vs I/O-Bound

Diagnosticando Load Average Alto: CPU-Bound vs I/O-Bound

O Que Você Vai Aprender

  • Como diferenciar se um load average alto é CPU-bound ou I/O-bound
  • O que o load average do Linux realmente conta (inclui I/O wait)
  • Exatamente onde olhar em uptime, top, vmstat e iostat

Resumo Rápido

  1. Verifique o load average com uptime e a quantidade de núcleos com nproc. load > núcleos significa sobrecarga.
  2. No vmstat 1, uma coluna r (runnable) alta significa saturação de CPU; uma coluna b alta mais wa significa I/O wait.
  3. Com a direção clara, investigue CPU com top/ps e I/O com iostat -x.

Premissas (ambiente)

  • SO: Ubuntu / Linux em geral
  • Shell: bash
  • Ferramentas: vmstat vem no pacote procps (geralmente pré-instalado); iostat e mpstat vêm no pacote sysstat (sudo apt install sysstat se ausente)

O que é load average e o que os números significam?

Conclusão: Load average é uma média movel exponencial do número de processos em execução, aguardando execução ou em I/O wait; os três valores do uptime são as médias de 1, 5 e 15 minutos.

Verifique com uptime ou cat /proc/loadavg.

$ uptime
 14:23:05  up 10 days,  3:42,  2 users,  load average: 4.85, 3.12, 1.90
$ cat /proc/loadavg
4.85 3.12 1.90 5/812 23145

Os três números são as médias de 1, 5 e 15 minutos, da esquerda para a direita. Compará-los mostra a tendência.

  • 1-min > 15-min (ex: 4.85 vs 1.90) → carga subindo
  • 1-min < 15-min → carga caindo
  • Todos os três próximos → carga estável e alta

Em /proc/loadavg, o 4o campo 5/812 é "processos em execução / total de processos", e o 5o é o PID mais recentemente criado.

Quão alto é "alto demais" para o load average?

Conclusão: Nunca julgue pelo número bruto. Compare com a quantidade de núcleos de CPU: quando load average / nucleos ultrapassa 1.0, o trabalho chega mais rápido do que os núcleos conseguem processar e os processos ficam aguardando.

Load average é uma contagem de processos aguardando, então mais núcleos elevam o valor aceitável.

$ nproc
4
  • 4 núcleos, load average 4.0 → essencialmente totalmente utilizado (fila próxima de zero)
  • 4 núcleos, load average 8.0 → 2x de sobrecarga (metade dos processos está na fila)

Use load / nucleos como regra prática.

load / núcleos Estado
~0.7 Folga
0.7-1.0 Quase cheio (fique atento)
> 1.0 Sobrecarregado (enfileirado)

Esta regra prática é para o caso de saturação de CPU. No Linux, I/O wait também conta no load, então você pode estar acima da quantidade de núcleos enquanto a CPU está praticamente ociosa. A próxima seção separa os dois.

Por que o load average do Linux não coincide com o uso de CPU?

Conclusão: O load average do Linux conta não apenas processos executáveis (TASK_RUNNING), mas também os em espera de I/O ininterruptível (TASK_UNINTERRUPTIBLE, estado D). Por isso o load pode disparar mesmo quando o uso de CPU é baixo.

Enquanto a maioria dos sistemas UNIX coloca apenas o tamanho da fila de execução da CPU no load, o Linux também inclui sleep ininterruptível (estado D no ps). O estado D vem principalmente de espera por I/O de disco ou armazenamento de rede.

Isso torna possíveis estados aparentemente contraditórios.

  • load average 8.0 mas uso de CPU (us+sy) é 10% → o restante é I/O wait acumulado
  • Armazenamento lento ou um mount NFS travado pode fazer o load disparar sozinho

"Load average alto" nem sempre significa "CPU ocupada". Saturação de CPU e I/O wait têm causas e soluções diferentes, então separe-os primeiro.

Como diferenciar CPU wait de I/O wait?

Conclusão: Leia a coluna r (runnable) e a coluna b (bloqueado em I/O) no vmstat 1, e %wa (iowait) no top. Um r grande significa saturação de CPU; um b grande e wa alto significam I/O wait.

Passo 1: Obtenha a tendência geral com vmstat

$ vmstat 1 5
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 6  0      0 124560  20480 890120    0    0     8    12  210  430 78 12 10  0  0
 5  0      0 124100  20480 890120    0    0     0     0  198  410 80 11  9  0  0

Duas colunas importam.

  • r (runnable): processos em execução ou aguardando CPU. Consistentemente acima da quantidade de núcleos → saturação de CPU.
  • b (blocked): processos em sleep ininterruptível (I/O, etc.). Grande → I/O wait.

Leia também wa (iowait, o percentual de tempo aguardando I/O) nas colunas de CPU. Acima, r=6 excede os 4 núcleos e wa=0, então é CPU-bound.

Passo 2: Confirme o detalhamento com top

$ top

Leia o detalhamento de CPU no cabeçalho.

%Cpu(s): 78.0 us, 12.0 sy,  0.0 ni, 10.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
  • us (user) + sy (system) altos → saturação de CPU. Pressione P para ordenar por CPU e encontrar o culpado.
  • wa (iowait) alto → I/O wait; a CPU está ociosa enquanto aguarda disco e similares.

Passo 3: Identifique os processos em estado D presos em I/O

Quando wa está alto, encontre quais processos estão bloqueados em I/O pela coluna de estado do ps (STAT).

$ ps -eo pid,stat,comm,wchan | awk '$2 ~ /D/'
  1842 D    mysqld          wait_on_page_bits
  1990 D+   dd              balance_dirty_pages

Processos cujo STAT é D (sleep ininterruptível) são os que estão aguardando I/O. O wchan (a função do kernel onde estão dormindo) indica a causa.

Passo 4: Corrobore pelo lado do disco com iostat

$ iostat -x 1 3
Device   r/s     w/s   rkB/s   wkB/s  await  aqu-sz  %util
sda      8.00  420.00   64.00 51200.0  85.20    9.80   99.6
  • %util próximo de 100% → esse dispositivo está saturado (não consegue processar mais I/O).
  • await grande (média de ms por I/O) → o disco está lento.
  • aqu-sz grande (tamanho médio da fila) → I/O está se acumulando.

Um %util próximo de 100% é a prova definitiva de carga I/O-bound.

Folha de consulta rápida

  • vmstat r alto, wa baixo → saturação de CPU
  • vmstat b alto, top wa alto, iostat %util alto → I/O wait
  • Ambos altos → CPU e I/O estão encadeados (ex: full-table scan em BD). Investigue ambos os lados.

O que fazer quando a causa é saturação de CPU?

Conclusão: Encontre o processo que consome CPU com top/ps. Se é um processo descontrolado, use renice ou pare-o; se é crônico, considere mais núcleos, distribuir o trabalho ou otimizar o código.

$ ps -eo pid,pcpu,comm --sort=-pcpu | head
  • Um processo descontrolado pontual → pare o processo ou reduza sua prioridade com renice.
  • Cronicamente acima da quantidade de núcleos → escale verticalmente (mais núcleos), paralelize/distribua o trabalho ou melhore o algoritmo.
  • Apenas em horários específicos → suspeite de jobs cron/batch agrupados e distribua seus agendamentos.

Para o fluxo completo de caca ao culpado, veja Diagnosticando uso de CPU a 100%.

O que fazer quando a causa é I/O wait?

Conclusão: Identifique o dispositivo saturado com iostat, depois encontre o processo gerando I/O com iotop. Excesso de logs, swap intenso e armazenamento lento são os culpados habituais.

$ sudo iotop -o
  • Um processo escreve pesadamente → suspeite de logging excessivo, full-table scan e similares.
  • si/so (colunas de swap do vmstat) estão se movendo → pressão de memória está causando swap. Veja Investigando pressão de memória.
  • O armazenamento em si é lento → substitua o dispositivo, revise o I/O scheduler ou reduza leituras/escritas.

Para uma investigação mais profunda de I/O de disco, veja Diagnosticando I/O de disco lento.

Armadilhas a evitar

  • Julgar apenas pelo número bruto de load (sempre compare com a quantidade de núcleos).
  • Ignorar wa e correr para adicionar CPUs (mais núcleos não resolvem I/O wait).
  • Tentar forçar kill em processos em estado D com kill -9 (geralmente não morrem até o I/O completar).

Resumo