Determinando corretamente o uso de memória no Linux

57

Estou um pouco confuso com alguns dos resultados que vejo em ps e free .

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".

Então, se eu entendi corretamente, o uso "real" é suposto ser o valor "usado" de "- / + buffers / cache", ou 561, neste caso.

Portanto, supondo que tudo isso esteja correto, a parte que me lança são os resultados de ps aux .

Meu entendimento dos resultados ps é que a sexta coluna (RSS) representa o tamanho em kilobytes que o processo usa para 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.

    
por GoldenNewby 23.03.2012 / 01:55

9 respostas

50

Esta 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 reportado used por free . Há muitas razões para isso, mas vou bater algumas das maiores.

  • Quando um processo se bifurca, o pai e o filho serão mostrados com o mesmo RSS. No entanto, o linux emprega copy-on-write para que ambos os processos realmente usem a mesma memória. Somente quando um dos processos modifica a memória será realmente duplicado. Portanto, isso fará com que o número free seja menor que a soma top RSS.

  • O valor de RSS não inclui memória compartilhada. Como a memória compartilhada não pertence a nenhum processo, top não a inclui no RSS. Portanto, isso fará com que o número free seja maior que a soma top RSS.

por 23.03.2012 / 20:48
27

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

smem is a tool that can give numerous reports on memory usage on Linux systems. Unlike existing tools, smem can report proportional set size (PSS), which is a more meaningful representation of the amount of memory used by libraries and applications in a virtual memory system.

Because large portions of physical memory are typically shared among multiple applications, the standard measure of memory usage known as resident set size (RSS) will significantly overestimate memory usage. PSS instead measures each application's "fair share" of each shared area to give a realistic measure.

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 

Então PSS é a coluna interessante aqui porque leva em conta a memória compartilhada.
Ao contrário de RSS , é significativo adicioná-lo. Obtemos 654Mb total para processos de userland aqui.

A saída do sistema informa 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 total de RAM = 654Mb processa 346Mb mem + 16Mb livre
(mais ou menos alguns Mb)

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

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

btw para algo visual tente:

# smem  --pie=name

    
por 20.11.2014 / 23:54
14

Uma ferramenta realmente boa é pmap , que lista o uso atual da memória para um determinado processo:

pmap -d PID

Para mais informações, veja a página de manual man pmap e também dê uma olhada em 20 Ferramentas de Monitoramento do Sistema Linux que Todo SysAdmin Deve Saber , que lista ótimas ferramentas que eu sempre uso para obter informações sobre minha caixa Linux.

    
por 23.03.2012 / 02:38
10

Execute o topo, pressione h para ajuda e f para adicionar campos. você pode adicionar os seguintes campos:

  • RSS da 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 estes 3 você deve ter resultados bastante precisos. Você também pode usar substituições mais detalhadas para o topo. Eu recomendo htop ou atop .

Editar: Quase esqueci se você deseja informações realmente detalhadas. Encontre o PID e cat o seguinte arquivo.

PID=123

cat /proc/123/status

Editar 2: Se você puder encontrar ou tiver o livro:

Optimizing Linux Performance: A Hands-On Guide to Linux Performance Tools

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

    
por 23.03.2012 / 02:13
5

ps fornece a quantidade de memória usada por cada processo. Alguma dessa memória é arquivos mmap, que conta sob o cache. Parte dessa memória (especialmente código) é compartilhada com outros processos, portanto, se você somar os valores de RSS, ela será contada várias vezes.

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

    
por 23.03.2012 / 20:39
4

Como outros apontaram corretamente, é difícil entender a memória real usada por um processo, o que acontece com regiões compartilhadas, arquivos mmap e outros.

Se você é um experimentador, pode executar valgrind e maciço . Isso pode ficar 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, então isso lhe dará uma boa representação do uso de memória dinâmica real de um processo. Mas esta experiência pode ser "envenenada".

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

// 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 marcar 16 GB de memória! (não, na verdade não).

Aviso em top você vê "VIRT" como 16.004G mas% MEM é 0.0

Execute novamente com valgrind:

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

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

MAS, se você executá-lo em um processo sane :

# 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 77KB de heap.

Por que tentar tanto usar apenas o 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 sobrecarga constante para um processo. De fato, as invocações subseqüentes do processo quase chegam "livres".

Além disso, compare e contraste o seguinte:

MMAP () um arquivo de 1GB. Seu VMSize será 1 GB. Mas o tamanho do conjunto de residentes será apenas as partes do arquivo que você fez com que paginasse (desreferindo um ponteiro para essa região). E se você "ler" todo o arquivo, então, quando você chegar ao fim, o kernel pode já ter paginado os primórdios (isso é fácil de fazer porque o kernel sabe exatamente como / onde substituir essas páginas se não for referenciado novamente ). Em ambos os casos, nem VMSize nem RSS são um bom indicador de sua "utilização" de memória. Você não fez nada de malloc ().

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

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

    
por 14.10.2016 / 18:41
1

Tente isto: ele vai te dar o total de RAM realmente usado por todo o processo rodando 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}'
    
por 04.03.2013 / 08:40
-1

Ele mostrará a você quantos usuários de memória os usuários.

#!/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
    
por 30.04.2013 / 21:57
-3

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

Memória utilizada:

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

memória livre

grep Mem | awk '{print $4/$2 * 100.0}'
    
por 11.12.2015 / 22:14

Tags