Comparando o tamanho da memória virtual com o tamanho do residente

0

Eu me deparei com este post de stackoverflow:

link

A resposta votada corretamente afirma o seguinte:

"Então, o VSS deve ser maior que o RSS. Se eles são parecidos, significa que seu processo está confortavelmente na memória. Se o VSS é muito maior, isso significa que não há memória suficiente e partes dele precisam ser trocado para o disco (ou seja, devido a um processo concorrente, etc.). "

Essa declaração me confunde muito, porque quando eu inspeciono meu sistema, percebo o seguinte.

Primeiro, percebo que tenho muita memória livre:

$ cat /proc/meminfo
MemTotal:        6113156 kB
MemFree:         3668992 kB

Isso significa que eu tenho 3,5 gigabytes de memória pura (sem swap, sem disco, etc)

No entanto, quando vejo meus processos filhos gerados pelo apache2, fico surpreso:

$ ps aux | grep apache2
USER       PID  %CPU %MEM  VSZ  RSS     TTY   STAT START    TIME    COMMAND
root      1130  0.0  0.1 149080 10600 ?        Ss   Jul11   0:03 /usr/sbin/apache2 -k start
www-data 23211  0.0  0.3 163408 23784 ?        S    10:34   0:03 /usr/sbin/apache2 -k start
www-data 23215  0.0  0.4 164436 24832 ?        S    10:34   0:02 /usr/sbin/apache2 -k start
www-data 23287  0.0  0.3 163608 23992 ?        S    10:36   0:02 /usr/sbin/apache2 -k start
www-data 23351  0.0  0.3 163660 24064 ?        S    10:40   0:01 /usr/sbin/apache2 -k start
www-data 23440  0.0  0.3 161580 23588 ?        S    10:46   0:00 /usr/sbin/apache2 -k start
www-data 24393  0.0  0.3 163620 23496 ?        S    11:32   0:00 /usr/sbin/apache2 -k start
www-data 25377  0.0  0.2 150656 12316 ?        S    12:20   0:00 /usr/sbin/apache2 -k start
www-data 25378  0.0  0.3 158224 18400 ?        S    12:20   0:00 /usr/sbin/apache2 -k start
www-data 27038  0.0  0.1 149360  7816 ?        S    13:01   0:00 /usr/sbin/apache2 -k start
www-data 27041  0.0  0.1 149368  7660 ?        S    13:01   0:00 /usr/sbin/apache2 -k start
1000     27124  0.0  0.0   8112   900 pts/0    S+   13:04   0:00 grep apache2

(Note que o grep remove os cabeçalhos das colunas, então eu os adiciono artificialmente de volta)

Veja quanta memória virtual maior é comparada à memória residente. Quero dizer, por exemplo, para o processo pai do apache (o processo pai é 1130):

$ ps xao pid,ppid,pgid,sid,comm | grep apache2 
 1130     1  1130  1130 apache2
23211  1130  1130  1130 apache2
23440  1130  1130  1130 apache2
27038  1130  1130  1130 apache2
27041  1130  1130  1130 apache2
27183  1130  1130  1130 apache2
27242  1130  1130  1130 apache2
27349  1130  1130  1130 apache2
27405  1130  1130  1130 apache2
27456  1130  1130  1130 apache2
27457  1130  1130  1130 apache2

Esse processo pai está ocupando 146 megabytes de memória virtual em comparação com 10 megabytes de memória residente. Essa é uma diferença de 136 megabytes de espaço de troca sendo usado!

Então isso não faz sentido para mim. Eu tenho muita memória livre, mas está usando muito mais espaço de troca? De acordo com o post no stackoverflow, ele diz "significa que não há memória suficiente". Bem, isso não é verdade. Eu tenho muita memória.

    
por JohnMerlino 12.07.2013 / 19:40

1 resposta

2

A conclusão "trocada" da postagem SO está errada. Por exemplo, aqui está um programa trivial:

#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>

int main() {
    printf("Started - sleeping 10s; pid = %i\n", (int)getpid());
    sleep(10);

    int fd = open("10469068800-byte-file", O_RDONLY);
    void *map = mmap(NULL, 10469068800, PROT_READ, MAP_SHARED, fd, 0);

    printf("Mapped - sleeping 10s; fd %i to %p\n", fd, map);
    sleep(10);

    return 0;
}

Quando eu verifico ps depois que ele imprime a mensagem iniciada (antes da mensagem mapeada ):

anthony@Zia:~$ ps u 13420
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
anthony  13420  0.0  0.0   4080   348 pts/13   S+   16:10   0:00 ./test

e depois:

USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
anthony  13420  0.0  0.0 10227780 348 pts/13   S+   16:10   0:00 ./test

Parte do espaço de endereço do programa está atualmente no disco, mas isso é porque é um arquivo mapeado na memória que ainda não foi lido (ou talvez nunca seja). Uma coisa semelhante acontece com este programa:

#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

int main() {
    printf("Started - sleeping 10s; pid = %i\n", (int)getpid());
    sleep(10);

    void *mem = malloc(1024*1024*1024);

    printf("Allocated - sleeping 10s; mem at %p\n", mem);
    sleep(10);

    return 0;
}

Antes:

USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
anthony  15150  0.0  0.0   4080   352 pts/13   S+   16:18   0:00 ./test2

Depois:

USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
anthony  15150  0.0  0.0 1052660  352 pts/13   S+   16:18   0:00 ./test2

Neste caso, a memória foi alocada mas, como uma otimização, o kernel não coloca páginas reais de memória atrás desses endereços até que o programa os use. Então, novamente, você vê um VSZ muito maior que o RSS.

Você provavelmente está vendo as duas coisas acima (e talvez mais algumas) no Apache. Você pode usar pmap -x para contar. Aqui está o que o segundo programa (o malloc) se parece:

anthony@Zia:~$ pmap -x 15997
15997:   ./test2
Address           Kbytes     RSS   Dirty Mode   Mapping
0000000000400000       4       4       0 r-x--  test2
0000000000600000       4       4       4 rw---  test2
00007fba82f94000 1048580       4       4 rw---    [ anon ]      <--- HERE
00007fbac2f95000    1672     300       0 r-x--  libc-2.17.so
00007fbac3137000    2048       0       0 -----  libc-2.17.so
00007fbac3337000      16      16      16 r----  libc-2.17.so
00007fbac333b000       8       8       8 rw---  libc-2.17.so
00007fbac333d000      16      12      12 rw---    [ anon ]
00007fbac3341000     132     104       0 r-x--  ld-2.17.so
00007fbac3533000      12      12      12 rw---    [ anon ]
00007fbac355f000      12      12      12 rw---    [ anon ]
00007fbac3562000       4       4       4 r----  ld-2.17.so
00007fbac3563000       8       8       8 rw---  ld-2.17.so
00007fffb7163000     132      12      12 rw---    [ stack ]
00007fffb71fe000       8       4       0 r-x--    [ anon ]
ffffffffff600000       4       0       0 r-x--    [ anon ]
----------------  ------  ------  ------
total kB         1052660     504      92

Note que você pode ver o mapeamento anônimo que é enorme, mas não tem quase nada residente. Para o programa com o mmap , você obtém:

Address           Kbytes     RSS   Dirty Mode   Mapping
⋮
00007f8e50cf2000 10223700       0       0 r--s-  10469068800-byte-file
⋮

Isso mostra que o arquivo de memória mapeada está lá, mas nenhum dele é residente.

    
por derobert 12.07.2013 / 22:21