Respostas:
RSS é o tamanho do conjunto residente e é usado para mostrar quanta memória é alocada para esse processo e está na RAM. Não inclui a memória trocada. Ele inclui memória de bibliotecas compartilhadas, desde que as páginas dessas bibliotecas estejam realmente na memória. Inclui toda a pilha e memória de pilha.
VSZ é o tamanho da memória virtual. Inclui toda a memória que o processo pode acessar, incluindo a memória trocada, a memória alocada, mas não usada, e a memória proveniente de bibliotecas compartilhadas.
Portanto, se o processo A tiver um binário de 500K e estiver vinculado a 2500K de bibliotecas compartilhadas, tiver 200K de alocações de pilha / heap, dos quais 100K estão realmente na memória (o restante é trocado ou não utilizado) e, na verdade, apenas 1000K foi carregado nas bibliotecas compartilhadas e 400K de seu próprio binário:
RSS: 400K + 1000K + 100K = 1500K
VSZ: 500K + 2500K + 200K = 3200K
Como parte da memória é compartilhada, muitos processos podem usá-la; portanto, se você adicionar todos os valores de RSS, poderá facilmente ter mais espaço do que o seu sistema.
A memória alocada também pode não estar no RSS até que seja realmente usada pelo programa. Portanto, se seu programa alocou um monte de memória antecipadamente e a utilizou com o tempo, você poderia ver o RSS subindo e o VSZ permanecendo o mesmo.
Há também PSS (tamanho proporcional do conjunto). Essa é uma medida mais recente que rastreia a memória compartilhada como uma proporção usada pelo processo atual. Portanto, se houvesse dois processos usando a mesma biblioteca compartilhada de antes:
PSS: 400K + (1000K/2) + 100K = 400K + 500K + 100K = 1000K
Todos os threads compartilham o mesmo espaço de endereço; portanto, o RSS, VSZ e PSS para cada thread são idênticos a todos os outros threads no processo. Use ps ou top para visualizar essas informações em linux / unix.
Há muito mais do que isso: para saber mais, verifique as seguintes referências:
Veja também:
libxml2.so, a biblioteca compartilhada será contada em cada um de seus RSS, portanto, a soma de seu RSS será mais do que a memória real usada.
topcomando. Este sistema não possui nenhuma troca, swapon --shownão retorna nada. Como você explica isso? Se vsz for swap + bibliotecas compartilhadas, nesse caso, as bibliotecas compartilhadas terão mais de 3.3G? É possível? Apenas realmente confuso ...
RSS é o tamanho do conjunto residente (memória fisicamente residente - atualmente ocupa espaço na memória física da máquina) e VSZ é tamanho da memória virtual (espaço de endereço alocado - isso possui endereços alocados no mapa de memória do processo, mas não há necessariamente nenhum memória real por trás de tudo agora).
Observe que nesses dias de máquinas virtuais comuns, a memória física do ponto de vista da máquina pode não ser realmente a memória física real.
Exemplo mínimo executável
Para que isso faça sentido, você precisa entender o básico da paginação: Como funciona a paginação x86? e, em particular, que o sistema operacional possa alocar memória virtual por meio de tabelas de páginas / sua manutenção de livro de memória interna (memória virtual VSZ) antes que ele realmente tenha um armazenamento de backup na RAM ou no disco (memória residente em RSS).
Agora, para observar isso em ação, vamos criar um programa que:
mmapmain.c
#define _GNU_SOURCE
#include <assert.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <unistd.h>
typedef struct {
unsigned long size,resident,share,text,lib,data,dt;
} ProcStatm;
/* /programming/1558402/memory-usage-of-current-process-in-c/7212248#7212248 */
void ProcStat_init(ProcStatm *result) {
const char* statm_path = "/proc/self/statm";
FILE *f = fopen(statm_path, "r");
if(!f) {
perror(statm_path);
abort();
}
if(7 != fscanf(
f,
"%lu %lu %lu %lu %lu %lu %lu",
&(result->size),
&(result->resident),
&(result->share),
&(result->text),
&(result->lib),
&(result->data),
&(result->dt)
)) {
perror(statm_path);
abort();
}
fclose(f);
}
int main(int argc, char **argv) {
ProcStatm proc_statm;
char *base, *p;
char system_cmd[1024];
long page_size;
size_t i, nbytes, print_interval, bytes_since_last_print;
int snprintf_return;
/* Decide how many ints to allocate. */
if (argc < 2) {
nbytes = 0x10000;
} else {
nbytes = strtoull(argv[1], NULL, 0);
}
if (argc < 3) {
print_interval = 0x1000;
} else {
print_interval = strtoull(argv[2], NULL, 0);
}
page_size = sysconf(_SC_PAGESIZE);
/* Allocate the memory. */
base = mmap(
NULL,
nbytes,
PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS,
-1,
0
);
if (base == MAP_FAILED) {
perror("mmap");
exit(EXIT_FAILURE);
}
/* Write to all the allocated pages. */
i = 0;
p = base;
bytes_since_last_print = 0;
/* Produce the ps command that lists only our VSZ and RSS. */
snprintf_return = snprintf(
system_cmd,
sizeof(system_cmd),
"ps -o pid,vsz,rss | awk '{if (NR == 1 || $1 == \"%ju\") print}'",
(uintmax_t)getpid()
);
assert(snprintf_return >= 0);
assert((size_t)snprintf_return < sizeof(system_cmd));
bytes_since_last_print = print_interval;
do {
/* Modify a byte in the page. */
*p = i;
p += page_size;
bytes_since_last_print += page_size;
/* Print process memory usage every print_interval bytes.
* We count memory using a few techniques from:
* /programming/1558402/memory-usage-of-current-process-in-c */
if (bytes_since_last_print > print_interval) {
bytes_since_last_print -= print_interval;
printf("extra_memory_committed %lu KiB\n", (i * page_size) / 1024);
ProcStat_init(&proc_statm);
/* Check /proc/self/statm */
printf(
"/proc/self/statm size resident %lu %lu KiB\n",
(proc_statm.size * page_size) / 1024,
(proc_statm.resident * page_size) / 1024
);
/* Check ps. */
puts(system_cmd);
system(system_cmd);
puts("");
}
i++;
} while (p < base + nbytes);
/* Cleanup. */
munmap(base, nbytes);
return EXIT_SUCCESS;
}
Compile e execute:
gcc -ggdb3 -O0 -std=c99 -Wall -Wextra -pedantic -o main.out main.c
echo 1 | sudo tee /proc/sys/vm/overcommit_memory
sudo dmesg -c
./main.out 0x1000000000 0x200000000
echo $?
sudo dmesg
Onde:
echo 1 | sudo tee /proc/sys/vm/overcommit_memory: necessário para o Linux nos permitir fazer uma chamada mmap maior que a RAM física: memória máxima que o malloc pode alocarSaída do programa:
extra_memory_committed 0 KiB
/proc/self/statm size resident 67111332 768 KiB
ps -o pid,vsz,rss | awk '{if (NR == 1 || $1 == "29827") print}'
PID VSZ RSS
29827 67111332 1648
extra_memory_committed 8388608 KiB
/proc/self/statm size resident 67111332 8390244 KiB
ps -o pid,vsz,rss | awk '{if (NR == 1 || $1 == "29827") print}'
PID VSZ RSS
29827 67111332 8390256
extra_memory_committed 16777216 KiB
/proc/self/statm size resident 67111332 16778852 KiB
ps -o pid,vsz,rss | awk '{if (NR == 1 || $1 == "29827") print}'
PID VSZ RSS
29827 67111332 16778864
extra_memory_committed 25165824 KiB
/proc/self/statm size resident 67111332 25167460 KiB
ps -o pid,vsz,rss | awk '{if (NR == 1 || $1 == "29827") print}'
PID VSZ RSS
29827 67111332 25167472
Killed
Status de saída:
137
que pela regra do número de sinal 128 + significa que obtivemos o número do sinal 9, que man 7 signalé SIGKILL , enviado pelo assassino de memória insuficiente do Linux .
Interpretação de saída:
printf '0x%X\n' 0x40009A4 KiB ~= 64GiB(os psvalores estão em KiB) após o mmap.extra_memory_committed 0, o que significa que ainda não tocamos nenhuma página. RSS é um pequeno 1648 KiBque foi alocado para a inicialização normal do programa, como área de texto, globais, etc.8388608 KiB == 8GiBvalor de páginas. Como resultado, o RSS aumentou exatamente 8GIB para8390256 KiB == 8388608 KiB + 1648 KiBConsulte também: /unix/35129/need-explanation-on-resident-set-size-virtual-size
Logs assassinos de OOM
Nossos dmesgcomandos mostraram os logs do OOM killer.
Uma interpretação exata deles foi solicitada em:
A primeira linha do log foi:
[ 7283.479087] mongod invoked oom-killer: gfp_mask=0x6200ca(GFP_HIGHUSER_MOVABLE), order=0, oom_score_adj=0
Portanto, vemos que, curiosamente, foi o daemon MongoDB que sempre é executado no meu laptop em segundo plano, o que desencadeou o assassino do OOM, provavelmente quando o pobre estava tentando alocar alguma memória.
No entanto, o assassino da OOM não mata necessariamente quem o acordou.
Após a chamada, o kernel imprime uma tabela ou processos, incluindo oom_score:
[ 7283.479292] [ pid ] uid tgid total_vm rss pgtables_bytes swapents oom_score_adj name
[ 7283.479303] [ 496] 0 496 16126 6 172032 484 0 systemd-journal
[ 7283.479306] [ 505] 0 505 1309 0 45056 52 0 blkmapd
[ 7283.479309] [ 513] 0 513 19757 0 57344 55 0 lvmetad
[ 7283.479312] [ 516] 0 516 4681 1 61440 444 -1000 systemd-udevd
e mais adiante, vemos que nosso pouco main.outfoi morto na invocação anterior:
[ 7283.479871] Out of memory: Kill process 15665 (main.out) score 865 or sacrifice child
[ 7283.479879] Killed process 15665 (main.out) total-vm:67111332kB, anon-rss:92kB, file-rss:4kB, shmem-rss:30080832kB
[ 7283.479951] oom_reaper: reaped process 15665 (main.out), now anon-rss:0kB, file-rss:0kB, shmem-rss:30080832kB
Esse log menciona o score 865que esse processo teve, presumivelmente a maior (pior) pontuação do assassino de OOM, conforme mencionado em: /unix/153585/how-does-the-oom-killer-decide-which- processo para matar primeiro
Curiosamente, tudo aparentemente aconteceu tão rápido que, antes que a memória liberada fosse contabilizada, ela oomfoi despertada novamente pelo DeadlineMonitorprocesso:
[ 7283.481043] DeadlineMonitor invoked oom-killer: gfp_mask=0x6200ca(GFP_HIGHUSER_MOVABLE), order=0, oom_score_adj=0
e desta vez que matou algum processo do Chromium, que geralmente é a memória normal de meus computadores:
[ 7283.481773] Out of memory: Kill process 11786 (chromium-browse) score 306 or sacrifice child
[ 7283.481833] Killed process 11786 (chromium-browse) total-vm:1813576kB, anon-rss:208804kB, file-rss:0kB, shmem-rss:8380kB
[ 7283.497847] oom_reaper: reaped process 11786 (chromium-browse), now anon-rss:0kB, file-rss:0kB, shmem-rss:8044kB
Testado no Ubuntu 19.04, kernel do Linux 5.0.0.
Acho que já foi dito muito sobre RSS vs VSZ. Do ponto de vista do administrador / programador / usuário, ao projetar / codificar aplicativos, estou mais preocupado com o RSZ (memória residente), pois e quando você continua puxando mais e mais variáveis (amontoadas), esse valor aumenta. Tente um programa simples para criar alocação de espaço com base em malloc em loop e certifique-se de preencher dados nesse espaço. O RSS continua subindo. No que diz respeito ao VSZ, é mais o mapeamento de memória virtual que o linux faz, e um de seus principais recursos derivados dos conceitos convencionais de sistema operacional. O gerenciamento do VSZ é feito pelo gerenciamento de memória virtual do kernel. Para obter mais informações sobre o VSZ, consulte a descrição de Robert Love em mm_struct e vm_struct, que fazem parte da estrutura básica de dados task_struct no kernel.
Eles não são gerenciados, mas medidos e possivelmente limitados (consulte a getrlimitchamada do sistema, também no getrlimit (2) ).
RSS significa tamanho do conjunto residente (a parte do seu espaço de endereço virtual localizado na RAM).
Você pode consultar o espaço de endereço virtual do processo 1234 usando proc (5) com cat /proc/1234/mapse seu status (incluindo consumo de memória) atravéscat /proc/1234/status