Determinando corretamente o uso de memória no Linux


63

Estou um pouco confuso com alguns dos resultados que estou vendo do ps e gratuito .

No meu servidor, este é o resultado de free -m

[root@server ~]# free -m
             total       used       free     shared    buffers     cached
Mem:          2048       2033         14          0         73       1398
-/+ buffers/cache:        561       1486
Swap:         2047         11       2036

Meu entendimento de como o Linux gerencia a memória é que ele armazenará o uso do disco na RAM, para que cada acesso subseqüente seja mais rápido. Eu acredito que isso é indicado pelas colunas "em cache". Além disso, vários buffers são armazenados na RAM, indicados na coluna "buffers".

Portanto, se eu entendi corretamente, o uso "real" deve ser o valor "usado" de "- / + buffers / cache" ou 561 neste caso.

Então, assumindo que tudo isso está correto, a parte que me joga é o resultado de ps aux.

Meu entendimento dos psresultados é que a 6a coluna (RSS) representa o tamanho em kilobytes que o processo usa para a memória.

Então, quando eu executo este comando:

[root@server ~]# ps aux | awk '{sum+=$6} END {print sum / 1024}'
1475.52

O resultado não deve ser a coluna "usada" de "- / + buffers / cache" de free -m?

Então, como posso determinar corretamente o uso de memória de um processo no Linux? Aparentemente, minha lógica é falha.


Esta questão é bastante popular e eu acho que eu deveria compartilhar uma resposta do htopautor a uma pergunta semelhante eu tive no outro dia ... Como calcular o uso de memória de / proc / meminfo (como htop)
tgogos

Respostas:


57

Este exata mesma pergunta foi feita em serverfault apenas no outro dia :-)

O sistema de memória virtual linux não é tão simples. Você não pode simplesmente adicionar todos os campos RSS e obter o valor relatado usedpor free. Existem muitas razões para isso, mas vou abordar algumas das maiores.

  • Quando um processo se bifurca, o pai e o filho são exibidos com o mesmo RSS. No entanto, o linux emprega copy-on-writepara que ambos os processos estejam realmente usando a mesma memória. Somente quando um dos processos modifica a memória será realmente duplicada. Portanto, isso fará com que o freenúmero seja menor que a topsoma do RSS.

  • O valor do RSS não inclui memória compartilhada. Como a memória compartilhada não pertence a nenhum processo, topnão a inclui no RSS. Portanto, isso fará com que o freenúmero seja maior que a topsoma do RSS.


11
Esta é a melhor resposta que recebi em qualquer site de troca de pilhas até o momento. Tão especificamente o que eu queria saber. É especialmente preciso para minha situação, porque estou lidando com um programa que escrevi para garfos de processos, mas a maior parte da pegada está nas bibliotecas que eles usam.
GoldenNewby

O problema com esta resposta é que o cálculo da soma de RSS e SHR geralmente fornece muito menos memória que o usado. Por exemplo, em um VPS que possuo, a memória usada é de 380 MB, enquanto a soma de todo o RSS e SHR é de 90 MB.
user239558

2
@ user239558 Como mencionei na resposta, há muitas razões pelas quais os números não somam, listei apenas 2 delas. Existem muitos outros números; cache, laje, páginas enormes etc.
Patrick #:

2
Provavelmente anos depois de você responder, ainda tenho (pelo menos) uma confusão. Você disse que o valor do RSS não inclui memória compartilhada, mas esta resposta disse que "Inclui memória de bibliotecas compartilhadas, desde que as páginas dessas bibliotecas estejam realmente na memória". Agora eu não sei qual a acreditar ... Talvez eu estou faltando algumas diferenças sutis aqui ...
Naitree

11
@Naitree "bibliotecas compartilhadas"! = "Memória compartilhada". memória compartilhada é algo como shmgetou mmap. As palavras em torno do material da memória são muito complicadas. Usar a palavra errada no lugar errado pode estragar totalmente o significado de uma frase.
Patrick

30

Se você está procurando números de memória que somam, dê uma olhada no smem :

O smem é uma ferramenta que pode fornecer vários relatórios sobre o uso de memória nos sistemas Linux. Diferentemente das ferramentas existentes, o smem pode relatar PSS (Proporcional Set Size), que é uma representação mais significativa da quantidade de memória usada por bibliotecas e aplicativos em um sistema de memória virtual.

Como grandes partes da memória física geralmente são compartilhadas entre vários aplicativos, a medida padrão do uso da memória, conhecida como RSS (tamanho do conjunto residente), superestima significativamente o uso da memória. Em vez disso, o PSS mede o "compartilhamento justo" de cada aplicativo de cada área compartilhada para fornecer uma medida realista.

Por exemplo aqui:

# smem -t
  PID User     Command                         Swap      USS      PSS      RSS
...
10593 root     /usr/lib/chromium-browser/c        0    22868    26439    49364 
11500 root     /usr/lib/chromium-browser/c        0    22612    26486    49732 
10474 browser  /usr/lib/chromium-browser/c        0    39232    43806    61560 
 7777 user     /usr/lib/thunderbird/thunde        0    89652    91118   102756 
-------------------------------------------------------------------------------
  118 4                                       40364   594228   653873  1153092 

O mesmo PSSvale para a coluna aqui, pois leva em consideração a memória compartilhada.
Ao contrário RSS, é significativo adicioná-lo. Temos um total de 654Mb para os processos da terra do usuário aqui.

A saída de todo o sistema fala sobre o resto:

# smem -tw
Area                           Used      Cache   Noncache 
firmware/hardware                 0          0          0 
kernel image                      0          0          0 
kernel dynamic memory        345784     297092      48692 
userspace memory             654056     181076     472980 
free memory                   15828      15828          0 
----------------------------------------------------------
                            1015668     493996     521672 

Então, 1Gb de RAM total = 654Mb de processos do usuário + 346Mb de memória do kernel + 16Mb grátis
(mais ou menos alguns Mb)

No geral, cerca de metade da memória é usada para cache (494Mb).

Pergunta de bônus : o que é cache do usuário versus cache do kernel aqui?


btw para algo visual tentar:

# smem  --pie=name

insira a descrição da imagem aqui


14

Uma ferramenta realmente boa é a pmaplista do uso atual da memória para um determinado processo:

pmap -d PID

Para obter mais informações, consulte a página de manual man pmape também veja 20 Ferramentas de Monitoramento do Sistema Linux que todo SysAdmin deve saber , que listam ótimas ferramentas que eu sempre uso para obter informações sobre minha caixa do Linux.


Essa é uma ferramenta muito legal, mas realmente não resolve o meu problema. Estou tentando descobrir como determinar efetivamente o uso de memória "real" no servidor.
GoldenNewby

3
@GoldenNewby Não existe o uso "real" de memória de um processo. O uso real da memória do sistema é o que freeinforma.
Gilles 'SO- stop be evil'

pmap -x PIDtambém inclui uma coluna RSS, que geralmente é bastante útil para ter uma idéia de onde a soma RSS de um processo (como observado, por exemplo, via topvem).
maxschlepzig

10

Execute o topo, pressione hajuda e fadicione campos. você pode adicionar os seguintes campos:

  • RSS quantidade de memória física que o aplicativo está usando
  • CODE quantidade total de memória que o código executável do processo está usando
  • DATA - quantidade total de memória (kb) dedicada aos dados e à pilha de um processo

Entre esses três, você deve ter resultados bastante precisos. Você também pode usar substituições mais detalhadas para o topo que eu recomendo htopou atop.

Edit: quase esqueci se você quiser informações realmente detalhadas. Encontre o PID e crie o arquivo a seguir.

PID=123

cat /proc/123/status

Editar 2: se você pode encontrá-lo ou tê-lo, o livro:

Otimizando o desempenho do Linux: um guia prático para ferramentas de desempenho do Linux

- possui uma seção Capítulo 5: Ferramentas de desempenho: memória específica de processo - possui muito mais informações do que você jamais desejaria.


Bem, por padrão, o tamanho do RSS do processo. Top fornece resultados idênticos aos do "ps aux" no meu exemplo. Minha pergunta é: como o RSS combinado de todos os processos é muito maior que o uso de memória "ativa" em todo o servidor?
GoldenNewby

5

psfornece a quantidade de memória usada por cada processo. Parte dessa memória são arquivos mmapped, que são contabilizados no cache. Parte dessa memória (especialmente o código) é compartilhada com outros processos; portanto, se você adicionar os valores de RSS, ele será contado várias vezes.

Não há resposta certa para “quanta memória esse processo usa?”, Porque não depende apenas do processo, mas também do ambiente. Há muitos valores diferentes que você pode chamar de "uso de memória" do processo, e eles não correspondem ou se somam porque estão contando coisas diferentes.


4

Como outros já apontaram corretamente, é difícil controlar a memória real usada por um processo, com regiões compartilhadas e com arquivos mapeados e outros enfeites.

Se você é um experimentador, pode executar valgrind e massif . Isso pode ser um pouco pesado para o usuário casual, mas você terá uma idéia do comportamento da memória de um aplicativo ao longo do tempo. Se um aplicativo malloc () é exatamente o que ele precisa, isso fornecerá uma boa representação do uso real da memória dinâmica de um processo. Mas esse experimento pode ser "envenenado".

Para complicar, o Linux permite que você comprometa demais sua memória. Quando você malloc () memória, você está declarando sua intenção de consumir memória. Mas a alocação não acontece realmente até você escrever um byte em uma nova página da sua "RAM" alocada. Você pode provar isso escrevendo e executando um pequeno programa em C da seguinte maneira:

// test.c
#include <malloc.h>
#include <stdio.h>
#include <unistd.h>
int main() {
    void *p;
    sleep(5)
    p = malloc(16ULL*1024*1024*1024);
    printf("p = %p\n", p);
    sleep(30);
    return 0;
}

# Shell:
cc test.c -o test && ./test &
top -p $!

Execute isso em uma máquina com menos de 16 GB de RAM e, voila!, Você acabou de ganhar 16 GB de memória! (Não, na verdade não).

Observe que topvocê vê "VIRT" como 16.004G, mas% MEM é 0.0

Execute isso novamente com valgrind:

# Shell:
valgrind --tool=massif ./test &
sleep 36
ms_print massif.out.$! | head -n 30

E o maciço diz "soma de todas as atribuições () = 16GB". Então isso não é muito interessante.

MAS, se você executá-lo em um processo são :

# Shell:
rm test test.o
valgrind --tool=massif cc test.c -o test &
sleep 3
ms_print massif.out.$! | head -n 30

--------------------------------------------------------------------------------
Command:            cc test.c -o test
Massif arguments:   (none)
ms_print arguments: massif.out.23988
--------------------------------------------------------------------------------


    KB
77.33^                                                                       :
     |                                                                      #:
     |                                                                :@::@:#:
     |                                                           :::::@@::@:#:
     |                                                         @:: :::@@::@:#:
     |                                                     ::::@:: :::@@::@:#:
     |                                             ::@:::@:::::@:: :::@@::@:#:
     |                                            @::@:::@:::::@:: :::@@::@:#:
     |                                            @::@:::@:::::@:: :::@@::@:#:
     |                      :@@@@@@@@@@@@@@@@@@@@:@::@:::@:::::@:: :::@@::@:#:
     |                      :@@                  :@::@:::@:::::@:: :::@@::@:#:
     |                    :@:@@                  :@::@:::@:::::@:: :::@@::@:#:
     |                    :@:@@                  :@::@:::@:::::@:: :::@@::@:#:
     |                   :@@:@@                  :@::@:::@:::::@:: :::@@::@:#:
     |                   :@@:@@                  :@::@:::@:::::@:: :::@@::@:#:
     |              :@::::@@:@@                  :@::@:::@:::::@:: :::@@::@:#:
     |          :::::@::::@@:@@                  :@::@:::@:::::@:: :::@@::@:#:
     |        :::::::@::::@@:@@                  :@::@:::@:::::@:: :::@@::@:#:
     |       ::::::::@::::@@:@@                  :@::@:::@:::::@:: :::@@::@:#:
     |       ::::::::@::::@@:@@                  :@::@:::@:::::@:: :::@@::@:#:
   0 +----------------------------------------------------------------------->Mi
     0                                                                   1.140

E aqui vemos (muito empiricamente e com muita confiança) que o compilador alocou 77 KB de heap.

Por que se esforçar tanto para obter apenas o uso de heap? Porque todos os objetos compartilhados e seções de texto que um processo usa (neste exemplo, o compilador) não são muito interessantes. Eles são uma sobrecarga constante para um processo. De fato, as invocações subsequentes do processo quase vêm de graça.

Além disso, compare e contraste o seguinte:

MMAP () um arquivo de 1 GB. Seu VMSize será de 1 + GB. Mas seu Tamanho do conjunto residente será apenas as partes do arquivo em que você causou a paginação (desreferenciando um ponteiro para essa região). E se você "ler" o arquivo inteiro, no momento em que chegar ao fim, o kernel poderá já ter paginado o início (isso é fácil de fazer, porque o kernel sabe exatamente como / onde substituir essas páginas, se desreferenciado novamente ) Em ambos os casos, nem o VMSize nem o RSS são um bom indicador do "uso" da sua memória. Você realmente não fez nada com malloc ().

Por outro lado, Malloc () e toque em MUITA memória - até que sua memória seja trocada para o disco. Portanto, sua memória alocada agora excede o seu RSS. Aqui, o seu VMSize pode começar a lhe dizer algo (seu processo possui mais memória do que o que realmente reside na sua RAM). Mas ainda é difícil diferenciar entre VMs que são páginas compartilhadas e VMs que são dados trocados.

É aqui que o valgrind / maciço se torna interessante. Ele mostra o que você alocou intencionalmente (independentemente do estado de suas páginas).


Eu tenho uma pergunta para você. Eu tenho um processo que mlock () s todos os seus arquivos mmap'ed. Existe uma maneira de determinar quanto dessa memória é usada ativamente - quanto dela foi lida ou gravada, digamos, nos últimos dois minutos?
22817 Michael Martinez

2

Tente o seguinte: ele fornecerá a RAM total realmente usada por todo o processo em execução em MB

ps -eo size,pid,user,command --sort -size | awk '
  { hr=$1/1024 ; printf("%13.2f Mb ",hr) } 
  { for ( x=4 ; x<=NF ; x++ ) { printf("%s ",$x) } print "" }
  ' | awk '{total=total + $1} END {print total}'

O sizerelatado por pstem pouca relação com o uso real de memória. É o tamanho virtual de cada processo que não é necessariamente alocado de memória. Também não inclui alguns segmentos que estão alocados.
Matt

-2

Ele mostrará a quantidade de memória que os usuários usam.

#!/bin/bash
total_mem=0

printf "%-10s%-10s\n" User MemUsage

while read u m
do
        [[ $old_user != $u ]] && {  printf "%-10s%-0.1f\n" $old_user $total_mem;
                                    total_mem=0; }
        total_mem="$(echo $m + $total_mem | bc)"
        old_user=$u

done < <(ps --no-headers -eo user,%mem| sort -k1)

#EOF

-3

Use este comando para encontrar a utilização da memória em%.

Memória utilizada:

grep Mem | awk '{print $3/$2 * 100.0}'

memoria livre

grep Mem | awk '{print $4/$2 * 100.0}'

3
Errr, isso não fará nada. grepvai ficar lá esperando por entrada.
mattdm

11
Isso deveria ter sido feitofree -m | grep Mem | awk '{print $3/$2 * 100.0}'
vjangus
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.