Como identificar o consumo de memória de um processo no Linux?
- por Sergio Prado
Então você precisa identificar o consumo de memória de um processo no Linux. Parece uma pergunta fácil de responder, não é verdade? Parece, mas não é!
Todo processo no Linux tem um arquivo no /proc que descreve detalhadamente seu uso de memória:
$ sudo cat /proc/1/smaps 7f3ba235d000-7f3ba2367000 r-xp 00000000 08:06 26877393 /lib/x86_64-linux-gnu/libnss_files-2.19.so Size: 40 kB Rss: 12 kB Pss: 0 kB Shared_Clean: 12 kB Shared_Dirty: 0 kB Private_Clean: 0 kB Private_Dirty: 0 kB Referenced: 12 kB Anonymous: 0 kB AnonHugePages: 0 kB Swap: 0 kB KernelPageSize: 4 kB MMUPageSize: 4 kB Locked: 0 kB VmFlags: rd ex mr mw me sd 7f3ba2367000-7f3ba2566000 ---p 0000a000 08:06 26877393 /lib/x86_64-linux-gnu/libnss_files-2.19.so Size: 2044 kB Rss: 0 kB Pss: 0 kB Shared_Clean: 0 kB Shared_Dirty: 0 kB Private_Clean: 0 kB Private_Dirty: 0 kB Referenced: 0 kB Anonymous: 0 kB AnonHugePages: 0 kB Swap: 0 kB KernelPageSize: 4 kB MMUPageSize: 4 kB Locked: 0 kB ... |
Alguns comandos, como o top, utilizam o arquivo acima para totalizar e exibir o consumo de memória de forma resumida:
$ top top - 17:55:01 up 1 day, 11:17, 6 users, load average: 0,26, 0,30, 0,30 Tasks: 328 total, 3 running, 321 sleeping, 3 stopped, 1 zombie %Cpu(s): 0,9 us, 0,5 sy, 0,0 ni, 98,4 id, 0,1 wa, 0,0 hi, 0,0 si, 0,0 st KiB Mem: 16400272 total, 14886920 used, 1513352 free, 1301036 buffers KiB Swap: 31249404 total, 119108 used, 31130296 free. 5523180 cached Mem PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 16494 sprado 20 0 520304 34068 9648 S 3,0 0,2 0:08.12 chrome 2056 root 20 0 1250340 718208 119328 S 2,7 4,4 110:36.08 Xorg 14582 sprado 20 0 659684 7560 4008 S 2,0 0,0 46:41.06 pulseaudio 18009 sprado 20 0 3168096 2,060g 2,023g S 2,0 13,2 934:51.85 vmware-vmx 19252 sprado 20 0 669952 24980 11036 S 1,3 0,2 2:21.39 gnome-terminal 14700 sprado 20 0 1757284 130748 32932 S 1,0 0,8 61:18.61 compiz ... |
Os campos VIRT, RES e SHR na saída do comando acima estão relacionados ao uso de memória, e falaremos sobre eles daqui a pouco. Mas já adianto que nenhum destes campos representa o uso real de memória física de um processo! Na verdade, não existe nenhum comando no Linux que vai te retornar esta informação, porque não é possível! O quê? Como assim???
É isso mesmo. E tudo é culpa de um pedacinho de hardware chamado MMU. Mas vamos começar do começo…
O Linux trabalha com memória virtual. Existe um chip chamado MMU (Memory Management Unit) localizado entre o processador e a memória RAM. Todo e qualquer acesso à memória passa por ele.
Os processos acessam a memória através de endereços virtuais. Durante o acesso à memória, a MMU consulta uma tabela de mapeamento (page table) e faz a conversão dos endereços virtuais do processos para os endereços físicos da RAM.
E para que serve tudo isso? Para muitas coisas, como por exemplo SWAP, controle de acesso, segurança e compartilhamento de memória. Se você tiver mais curiosidade sobre o funcionamento da MMU e suas vantagens, consulte o artigo “O Linux em sistemas sem MMU e o uClinux“.
Voltando à saída do comando top, o valor do campo VIRT (Virtual Memory Size) representa a quantidade total de memória virtual mapeada para um processo. Por exemplo, o chrome possui em torno de 520MB de memória virtual mapeada para ele. Mas isso não significa que tudo isso está mapeado em memória física. Por exemplo, parte deste mapeamento virtual pode estar em SWAP (disco).
Por outro lado, o campo RES (Resident Memory Size) indica a quantidade de memória mapeada fisicamente para o processo (aproximadamente 34MB no exemplo do chrome). Mas este campo também não indica a quantidade de memória física total utilizada pelo processo! Como assim???
Outros processos podem estar compartilhando memória com ele. Por exemplo, quando o kernel carrega o código de uma biblioteca para a memória RAM, ele pode mapear esta mesma região de memória física para todos os processos que querem utilizar a biblioteca, economizando assim memória RAM, porque a biblioteca é carregada uma vez só e compartilhada por múltiplos processos. Um exemplo clássico é a biblioteca do sistema (libc).
Na prática, isso significa que, se eu encerrar a execução do chrome, não serão liberados os 34MB de memória exibidos na listagem do comando top, porque parte desta memória é compartilhada com outros processos. Portanto, este campo não serve como referência para a memória física utilizada (unica e exclusivamente) pelo processo.
Por fim, o campo SHR (Shared Memory Size) representa a quantidade de memória que este processo está compartilhando com outros processos. Também não serve diretamente para o propósito de identificar a quantidade de memória física consumida pelo processo.
Sim, o buraco é muito mais embaixo. Na prática, só é possível identificar o uso aproximado de memória de um processo!
Uma forma é identificar a quantidade de memória física consumida de forma exclusiva pelo processo e somar com uma proporção da quantidade de memória compartilhada com outros processos. É basicamente isso que o comando smem faz!
$ smem -r PID User Command Swap USS PSS RSS 14925 sprado /usr/lib/x86_64-linux-gnu/z 0 413216 413479 417144 15048 sprado /opt/google/chrome/chrome 0 383364 395453 425564 20161 sprado /opt/google/chrome/chrome - 0 236084 245963 286940 18867 sprado /opt/google/chrome/chrome - 0 231452 235478 270032 20015 sprado /opt/google/chrome/chrome - 0 144484 148761 184072 14796 sprado /home/sprado/.dropbox-dist/ 0 138012 138268 144440 15289 sprado /opt/google/chrome/chrome - 0 120904 123651 153916 14700 sprado compiz 0 102500 111868 130964 15494 sprado /opt/google/chrome/chrome - 0 89572 93431 128036 16554 sprado /opt/google/chrome/chrome - 0 83612 90005 127016 13176 sprado /opt/google/chrome/chrome - 0 59864 62301 89460 14721 sprado nautilus -n 0 23956 49293 83968 17185 sprado /usr/lib/vmware/bin/vmware 0 45268 48599 61124 15301 sprado /opt/google/chrome/chrome - 0 45820 48035 75116 14387 sprado /usr/lib/x86_64-linux-gnu/h 0 41320 42137 49604 14669 sprado /usr/lib/evolution/evolutio 0 37432 37524 40840 15291 sprado /opt/google/chrome/chrome - 0 32632 35128 64268 18391 sprado gedit /home/sprado/Dropbox/ 0 29296 31248 42696 20714 sprado /usr/bin/python3 /usr/share 0 22836 23055 26532 15296 sprado /opt/google/chrome/chrome - 0 18536 21235 50972 14401 sprado /usr/lib/unity/unity-panel- 0 19944 20604 29572 17225 sprado /usr/lib/vmware/bin/vmware- 0 15152 16640 24724 19252 sprado gnome-terminal 0 15148 16224 25624 20850 sprado vim lwip/src/arch/lpc17xx_4 0 15384 15904 18336 17148 sprado /usr/bin/unity-scope-loader 0 14872 15090 18664 15298 sprado /opt/google/chrome/chrome - 0 11672 13538 38664 |
O campo USS (Unique Set Size) representa a quantidade de memória física mapeada de forma exclusiva para o processo, e somando mais uma proporção da memória compartilhada com outros processos tem-se o campo PSS (Proportional Set Size), que é o que você vai ter de mais perto do consumo de memória de um processo no Linux!
Satisfeito? :)
Happy hacking!
Sergio Prado