Estou um pouco confuso com alguns dos resultados que estou vendoobs:elivre.
No meu servidor, este é o resultado defree -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 subsequente seja mais rápido. Acredito que isso seja indicado pelas colunas "em cache". Além disso, vários buffers são armazenados na RAM, indicados na coluna “buffers”.
Então, se bem entendi, o uso "real" deve ser o valor "usado" de "-/+ buffers/cache", ou 561 neste caso.
Então, supondo que tudo isso esteja correto, a parte que me surpreende são os resultados de ps aux
.
Meu entendimento dos ps
resultados é que a 6ª coluna (RSS) representa o tamanho em kilobytes que o processo usa para memória.
Então, quando executo este comando:
[root@server ~]# ps aux | awk '{sum+=$6} END {print sum / 1024}'
1475.52
O resultado não deveria 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.
Responder1
Copie/cole descaradamente minha resposta defalha no servidoroutro dia mesmo :-)
O sistema de memória virtual Linux não é tão simples. Você não pode simplesmente somar todos os campos RSS e obter o valor relatado used
por free
. Há muitas razões para isso, mas abordarei algumas das maiores.
Quando um processo se bifurca, tanto o pai quanto o filho serão exibidos com o mesmo RSS. No entanto, o Linux emprega cópia na gravação para que ambos os processos realmente usem a mesma memória. Somente quando um dos processos modificar a memória ela será realmente duplicada.
Isso fará com que ofree
número seja menor que atop
soma do RSS.O valor 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.
Isso fará com que ofree
número seja maior que atop
soma do RSS.
Existem muitos outros motivos pelos quais os números podem não bater. Esta resposta está apenas tentando deixar claro que o gerenciamento de memória é muito complexo e você não pode simplesmente adicionar/subtrair valores individuais para obter o uso total da memória.
Responder2
Se você está procurando números de memória que se somam, dê uma olhada emsmem:
smem é uma ferramenta que pode fornecer vários relatórios sobre o uso de memória em sistemas Linux. Ao contrário das ferramentas existentes, o smem pode relatar o tamanho do conjunto proporcional (PSS), 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 porções de memória física são normalmente compartilhadas entre vários aplicativos, a medida padrão de uso de memória conhecida como tamanho do conjunto residente (RSS) superestimará significativamente o uso de memória. Em vez disso, o PSS mede a “parcela justa” de cada aplicação em 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
A coluna aqui também PSS
é interessante porque leva em consideração a memória compartilhada.
Ao contrário, RSS
é significativo somar. Obtemos um total de 654 MB para processos de usuário aqui.
A saída de todo o 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
Portanto, 1 Gb de RAM total = 654 Mb de processos de usuário + 346 Mb de memória do kernel + 16 Mb livres
(mais ou menos alguns Mb)
No geral, cerca de metade da memória é usada para cache (494Mb).
Pergunta bônus: o que é cache do usuário versus cache do kernel aqui?
aliás, para algo visual, tente:
# smem --pie=name
Responder3
Uma ferramenta realmente boa é pmap
listar o uso atual de memória para um determinado processo:
pmap -d PID
Para obter mais informações sobre isso, consulte a página de manual man pmap
e também dê uma olhada em20 ferramentas de monitoramento de sistema Linux que todo SysAdmin deve conhecer, que lista ótimas ferramentas que sempre uso para obter informações sobre minha caixa Linux.
Responder4
Como outros apontaram corretamente, é difícil controlar a memória real usada por um processo, com regiões compartilhadas, arquivos mmap'ed e outros enfeites.
Se você é um experimentador, você pode executarvalgrind e maciço. Isso pode ficar um pouco pesado para o usuário casual, mas você terá uma ideia do comportamento da memória de um aplicativo ao longo do tempo. Se um aplicativo malloc() for exatamente o que ele precisa, isso fornecerá uma boa representação do uso real da memória dinâmica de um processo. Mas esta experiência pode ser “envenenada”.
Para complicar as coisas, o Linux permite que vocêcomprometer demaissua memória. Ao usar a memória malloc(), você está declarando sua intenção de consumir memória. Mas a alocação realmente não acontece até que você grave um byte em uma nova página da sua "RAM" alocada. Você pode provar isso escrevendo e executando um pequeno programa em C como este:
// 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, pronto!, você acabou de ganhar 16 GB de memória! (Não, na verdade não).
Observe que top
você 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 todos os allocs() = 16GB". Então isso não é muito interessante.
MAS, se você executá-lo em umsãoprocesso:
# 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 uma confiança muito alta) que o compilador alocou 77 KB de heap.
Por que tentar tanto obter apenas o uso do 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. Na verdade, as invocações subsequentes do processo são quase “de graça”.
Além disso, compare e contraste o seguinte:
MMAP() um arquivo de 1 GB. Seu VMSize será 1+GB. Mas seu tamanho do conjunto residente será apenas as partes do arquivo que você fez com que fossem paginadas (desreferenciando um ponteiro para essa região). E se você "ler" o arquivo inteiro, quando chegar ao final, o kernel já poderá ter paginado o início (isso é fácil de fazer porque o kernel sabe exatamente como/onde substituir essas páginas se forem desreferenciadas novamente ). Em ambos os casos, nem VMSize nem RSS são um bom indicador do "uso" de sua memória. Na verdade, você não fez malloc() nada.
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 seu RSS. Aqui, seu VMSize pode começar a lhe dizer algo (seu processo possui mais memória do que realmente reside em sua RAM). Mas ainda é difícil diferenciar entre VM que são páginas compartilhadas e VM que são dados trocados.
É aqui que valgrind/massif se torna interessante. Isso mostra o que você temintencionalmentealocado (independentemente do estado de suas páginas).