Linux: Troca total usada = troca usada pelos processos +?

17

Então, estou tentando fazer alguma investigação sobre de onde vem o uso de troca em um sistema com alto uso de troca:

# free
             total       used       free     shared    buffers     cached
Mem:        515324     508800       6524          0       4852      27576
-/+ buffers/cache:     476372      38952
Swap:       983032     503328     479704

Adicionando swap usado por processo:

# for proc in /proc/*; do cat $proc/smaps 2>/dev/null | awk '/Swap/{swap+=$2}END{print swap "\t'`readlink $proc/exe`'"}'; done | sort -n | awk '{total+=$1}/[0-9]/;END{print total "\tTotal"}'
0       /bin/gawk
0       /bin/sort
0       /usr/bin/readlink
28      /sbin/xxxxxxxx
52      /sbin/mingetty
52      /sbin/mingetty
52      /sbin/mingetty
52      /sbin/mingetty
56      /sbin/mingetty
56      /sbin/mingetty
60      /xxxxxxxxxxx
60      /usr/sbin/xxx
84      /usr/sbin/xxx
108     /usr/bin/xxx
168     /bin/bash
220     /sbin/init
256     /sbin/rsyslogd
352     /bin/bash
356     /bin/bash
360     /usr/sbin/sshd
496     /usr/sbin/crond
672     /usr/sbin/sshd
12972   /opt/jdk1.6.0_22/bin/java
80392   /usr/libexec/mysqld
311876  /opt/jdk1.6.0_22/bin/java
408780  Total

O que fornece um valor mais baixo para o total de swap usado. Onde está o espaço de troca usado restante? É memória vmalloc () dentro do kernel? Algo mais? Como posso identificá-lo?

Saída de meminfo:

# cat /proc/meminfo 
MemTotal:       515324 kB
MemFree:          6696 kB
Buffers:          5084 kB
Cached:          28056 kB
SwapCached:     157512 kB
Active:         429372 kB
Inactive:        65068 kB
HighTotal:           0 kB
HighFree:            0 kB
LowTotal:       515324 kB
LowFree:          6696 kB
SwapTotal:      983032 kB
SwapFree:       478712 kB
Dirty:             100 kB
Writeback:           0 kB
AnonPages:      399456 kB
Mapped:           8792 kB
Slab:             7744 kB
PageTables:       1820 kB
NFS_Unstable:        0 kB
Bounce:              0 kB
CommitLimit:   1240692 kB
Committed_AS:  1743904 kB
VmallocTotal:   507896 kB
VmallocUsed:      3088 kB
VmallocChunk:   504288 kB
HugePages_Total:     0
HugePages_Free:      0
HugePages_Rsvd:      0
Hugepagesize:     4096 kB
ninj
fonte
Buffers e cache estão incluídos e não estão associados a nenhum processo.
Goldilocks
2
@ goldilocks: não, esses estão na memória física. Além disso, eles não se somam.
N
Você está certo, acho que armazenar coisas em cache para trocar seria meio inútil. No entanto, acho que as coisas trocadas podem ser deixadas lá e rastreadas mesmo após o processo que possui é extinto, desde que esse espaço de troca não seja necessário; isso economiza tempo mais tarde, se um processo carregar a mesma página e, em seguida, essa página precisar ser trocada novamente - ela ainda estará lá na troca. Google "swap cache" do linux-tutorial.info/modules.php?name=MContent&pageid=314 Isso é paralelo à criação do "cache de cache" real (são coisas salvas na memória a partir de processos agora extintos).
Goldilocks
... significando, lol, que "armazenar coisas em cache na troca" não é tão inútil, apenas que não chega lá trocando o cache da RAM.
Goldilocks
1
Não é a resposta apenas que o kernel pode trocar e isso não está incluído no seu processamento? Atualmente, o kernel tem um monte de processos de "espaço do usuário" hoje em dia ... Apenas um palpite.
Iain

Respostas:

11

A diferença que você está observando não se deve ao fato de o espaço de troca não ser contabilizado. O "(excluído)" que o kernel às vezes anexa aos /proc/*/exelinks é produzido readlinke está causando erros de análise no seu script awk, e você efetivamente não está contando processos cujos binários não estão mais presentes no seu total.

Alguns kernels anexam a palavra "(excluído)" aos /proc/*/exelinks simbólicos de destino quando o executável original do processo não está mais por perto.

A razão pela qual seu comando está mostrando menos que o total é por causa disso. A saída readlinkdesses links será algo como "/ caminho / para / bin (excluído)", que causa um erro de análise awkquando a saída é substituída novamente na cadeia de caracteres (não gosta de parênteses e espaços). Por exemplo, faça o seguinte:

for a in /proc/*/exe ; do readlink $a ; done | grep deleted

E você verá algumas entradas com "(excluído)" anexado. Se você observasse o uso de troca dessas entradas, o total delas corresponderia à discrepância que você vê, pois os awkerros resultantes impedem que os totais sejam calculados e incluídos no total final.

Se você executar o comando original sem redirecionar o stderr para qualquer lugar, provavelmente notará alguns erros de "constante da cadeia de fuga". Esses erros são o resultado do exposto acima e você não deveria tê-los ignorado.

Ignorando outras melhorias em potencial no seu comando original, você pode modificá-lo removendo o "(excluído)", desta forma (observação |awk '{print $1}'adicionada à readlinksaída):

for proc in /proc/*; \
  do cat $proc/smaps 2>/dev/null | awk '/Swap/{swap+=$2}END{print swap "\t'`readlink $proc/exe|awk '{print $1}' `'" }'; \
done | sort -n | awk '{total+=$1}/[0-9]/;END{print total "\tTotal"}'

Esse uso de awkpara corrigir a saída de readlinkpode ser interrompido se o nome contiver espaços - você pode usar sedou o método que preferir.

Informações sobre bônus

A propósito, você poderia apenas usar smem -t. A coluna "Trocar" exibe o que você deseja.

No entanto, quanto ao cálculo, você também pode obter essas informações mais diretamente do VmSwapcampo /proc/*/status(smaps requer algum suporte do kernel e nem sempre está disponível) e evite redirecionar a saída de erros usando um padrão de nome de arquivo adequado que evite o erros para começar:

for proc in /proc/[0-9]*; do \
  awk '/VmSwap/ { print $2 "\t'`readlink $proc/exe | awk '{ print $1 }'`'" }' $proc/status; \
done | sort -n | awk '{ total += $1 ; print $0 } END { print total "\tTotal" }'

Se você não precisa do binário real e pode lidar com apenas ter o nome do processo, você pode obter tudo a partir de status:

for a in /proc/*/status ; do \
  awk '/VmSwap|Name/ { printf $2 " " } END { print "" }' $a ; \
done | awk '{ total+=$2 ; print $0 } END { print "Total " total }'

E, finalmente, se apenas ter os PIDs for suficiente, você pode fazer tudo com awk:

awk '/VmSwap/ { total += $2; print $2 "\t" FILENAME } END { print total "\tTotal" }' /proc/*/status

Nota:

Agora, isso não quer dizer que não haja diferenças entre freee smem(o último sendo o mesmo que o seu script). Existem muitos (consulte, por exemplo, https://www.google.com/search?q=smem+free , que possui resultados mais do que suficientes na primeira página para responder às suas perguntas sobre o uso da memória). Mas sem um teste adequado, sua situação específica não pode ser resolvida.

Jason C
fonte
5

O swap também é usado pelo tmpfs se o kernel precisar de mais RAM livre ou simplesmente porque não é usado por algum tempo ... então qualquer uso do tmpfs pode consumir swap.

higuita
fonte
1
Por que o voto negativo? Isto está absolutamente correto.
Jlliagre 23/10/2013