En la salida de atop de un servidor Linux me encontré con esta situación extraña:

Si queda memoria principal disponible y el uso de swap es cero, ¿por qué la fila SWP figura en color rojo (uso crítico)?

Esto se debe a que el sistema operativo ha entregado a los procesos más memoria de la que dispone. Del manual de atop (man atop):

If  the  committed  virtual  memory exceeds the limit (`vmcom' and
`vmlim' in the SWP-line), the SWP-line is colored due to  overcom-
mitting the system.

Cuando un sistema operativo asigna memoria a un proceso en el espacio usuario, no existe una correspondencia fija entre las páginas de memoria virtual en el espacio de memoria del proceso y la memoria física de la máquina (frames). De hecho, antes de que la memoria asignada sea utilizada por primera vez, es probable que no exista ninguna correspondencia a memoria física. Sólo luego del primer intento de acceso a memoria el kernel se encarga de reservar el espacio correspondiente en memoria física.

Esto significa que el sistema operativo puede asignar a un proceso una cantidad de memoria prácticamente ilimitada, siempre y cuando éste no intente accederla al mismo tiempo. Overcommit se refiere justamente a esta práctica: asignar memoria virtual sin garantía de que exista almacenamiento físico para la misma. Ya sea memoria principal (RAM) o memoria secundaria (swap o área de intercambio). En este contexto, el sistema operativo continúa entregando memoria virtual hasta que un programa toca una página previamente no tocada y el kernel no puede encontrar memoria física disponible para instanciarla. Así las cosas empiezan a fallar de forma horrible.

En Linux, cuando la memoria física (RAM + swap) se agota, ocurre un evento OOM (Out Of Memory) en el kernel, el cual utiliza un algoritmo para determinar qué proceso es el culpable de agotar la memoria, para luego matar dicho proceso. Esto en la práctica funciona relativamente bien, pues se evitan matar procesos críticos del sistema y se mata el proceso consumiendo demasiada memoria. Pero en realidad ningún proceso es realmente culpable de usar más memoria de la disponible, pues a ninguno se le dijo que la memoria física era insuficiente al momento de reservarla.

La estrategia para evitar el overcommitting consiste en llevar la cuenta de cuanta memoria se ha asignado. Esto es lo que hace Linux cuando se configura el parámetro vm.overcommit_memory en 2. De esta forma, toda la memoria que pueda ser potencialmente accesible (ya sea en memoria principal como en swap) cuenta como memoria asignada a procesos y aplicaciones. Cuando una solicitud de memoria de un proceso provoca que la asignación total sobrepase un límite configurado (por defecto el tamaño del área de intercambio más la mitad de la memoria RAM), la solicitud falla.

Desafortunadamente a la mayoría de desarrolladores de aplicaciones les gusta pedir memoria de más (overcommit). Ya sea porque ésto permite contar con cantidades ridículas de memoria (siempre que se haga un uso responsable de la misma), o por pereza al momento de verificar errores (ignorar el código de retorno de malloc).

Sea como sea, puede ser prácticamente imposible para un SysAdmin controlar el uso de memoria de una aplicación desarrollada por terceros (más allá de que sea de código abierto), por lo que hay que estar atentos ante estas situaciones. En caso de máquinas virtuales, es posible agregar más memoria RAM, pues de todas formas no es memoria que se está utilizando sino que simplemente está reservada. De esta forma sería posible evitar eventuales OOM en el kernel Linux.

Sin embargo, la alternativa correcta sería determinar qué procesos o servicios son responsables por el elevado consumo de memoria (virtual). Para ello se puede recurrir a la herramienta ps, la cual muestra en su salida el tamaño del espacio de memoria virtual de cada proceso:

root@linuxito:~# ps aux | grep /usr/sbin/mysqld
root      6754  0.0  0.1   7732   940 pts/0    S+   09:42   0:00 grep /usr/sbin/mysqld
mysql    23778  0.3  6.3 598152 33312 ?        Sl   Aug24  55:14 /usr/sbin/mysqld --basedir=/usr --datadir=/var/lib/mysql --plugin-dir=/usr/lib/mysql/plugin --user=**** --pid-file=/var/run/mysqld/mysqld.pid --socket=/var/run/mysqld/mysqld.sock --port=****

La quinta columna describe el tamaño del espacio de memoria virtual del proceso (VSZ). De acuerdo al manual de ps:

vsz         VSZ       virtual memory size of the process in KiB (1024-byte units).

Luego será necesario ajustar la configuración del proceso o servicio acaparando el uso de memoria (dentro de lo que el servicio permita y sea factible para que funcione correctamente) revisando cuidadosamente su documentación, tal como por ejemplo expliqué en mi artículo Tunning de InnoDB para reducir al mínimo el consumo de memoria.

Otra forma de examinar detalladamente el consumo de memoria de un proceso puede ser recurriendo a la herramienta pmap, la cual muestra el mapeo de memoria de un proceso:

root@linuxito:~# pmap -x 23778
23778:   /usr/sbin/mysqld --basedir=/usr --datadir=/var/lib/mysql --plugin-dir=/usr/lib/mysql/plugin --user=**** --pid-file=/var/run/mysqld/mysqld.pid --socket=/var/run/mysqld/mysqld.sock --port=****
Address           Kbytes     RSS   Dirty Mode   Mapping
00007f9944000000   11208    1548    1548 rw---    [ anon ]
00007f9944af2000   54328       0       0 -----    [ anon ]
00007f9948000000    3496      84      84 rw---    [ anon ]
00007f994836a000   62040       0       0 -----    [ anon ]
00007f994c000000    2096      24      24 rw---    [ anon ]
00007f994c20c000   63440       0       0 -----    [ anon ]
00007f9950000000    2364     128     128 rw---    [ anon ]
00007f995024f000   63172       0       0 -----    [ anon ]
00007f9954000000    8484    1708    1708 rw---    [ anon ]
00007f9954849000   57052       0       0 -----    [ anon ]
00007f9959706000       4       0       0 -----    [ anon ]
00007f9959707000     192       0       0 rw---    [ anon ]
00007f9959737000       4       0       0 -----    [ anon ]
00007f9959738000     192       0       0 rw---    [ anon ]
00007f9959768000       4       0       0 -----    [ anon ]
00007f9959769000     192       0       0 rw---    [ anon ]
00007f9959799000       4       0       0 -----    [ anon ]
00007f995979a000     192       0       0 rw---    [ anon ]
00007f99597ca000       4       0       0 -----    [ anon ]
00007f99597cb000     192       0       0 rw---    [ anon ]
00007f99597fb000       4       0       0 -----    [ anon ]
00007f99597fc000     192       0       0 rw---    [ anon ]
00007f995982c000       4       0       0 -----    [ anon ]
00007f995982d000     192      60      60 rw---    [ anon ]
00007f995985d000       4       0       0 -----    [ anon ]
00007f995985e000     192       0       0 rw---    [ anon ]
00007f995988e000       4       0       0 -----    [ anon ]
00007f995988f000     192      60      60 rw---    [ anon ]
00007f99598bf000       4       0       0 -----    [ anon ]
00007f99598c0000     192      60      60 rw---    [ anon ]
00007f99598f0000       4       0       0 -----    [ anon ]
00007f99598f1000     192       0       0 rw---    [ anon ]
00007f9959921000       4       0       0 -----    [ anon ]
00007f9959922000     192       0       0 rw---    [ anon ]
00007f9959952000       4       0       0 -----    [ anon ]
00007f9959953000     192       0       0 rw---    [ anon ]
00007f9959983000       4       0       0 -----    [ anon ]
00007f9959984000     192       0       0 rw---    [ anon ]
00007f99599b4000       4       0       0 -----    [ anon ]
00007f99599b5000     192       0       0 rw---    [ anon ]
00007f99599e5000       4       0       0 -----    [ anon ]
00007f99599e6000     192       0       0 rw---    [ anon ]
00007f9959a16000       4       0       0 -----    [ anon ]
00007f9959a17000     192       0       0 rw---    [ anon ]
00007f9959a47000       4       0       0 -----    [ anon ]
00007f9959a48000     192       0       0 rw---    [ anon ]
00007f9959a78000       4       0       0 -----    [ anon ]
00007f9959a79000     192       0       0 rw---    [ anon ]
00007f9959aa9000       4       0       0 -----    [ anon ]
00007f9959aaa000     192       0       0 rw---    [ anon ]
00007f9959ada000       4       0       0 -----    [ anon ]
00007f9959adb000     192       0       0 rw---    [ anon ]
00007f9959b0b000       4       0       0 -----    [ anon ]
00007f9959b0c000     192       0       0 rw---    [ anon ]
00007f9959b3c000       4       0       0 -----    [ anon ]
00007f9959b3d000     192       0       0 rw---    [ anon ]
00007f9959b6d000       4       0       0 -----    [ anon ]
00007f9959b6e000     192       0       0 rw---    [ anon ]
00007f9959b9e000       4       0       0 -----    [ anon ]
00007f9959b9f000     192       0       0 rw---    [ anon ]
00007f9959bcf000       4       0       0 -----    [ anon ]
00007f9959bd0000     192       0       0 rw---    [ anon ]
00007f9959c00000       4       0       0 -----    [ anon ]
00007f9959c01000     192       0       0 rw---    [ anon ]
00007f9959c31000       4       0       0 -----    [ anon ]
00007f9959c32000     192       0       0 rw---    [ anon ]
00007f9959c62000       4       0       0 -----    [ anon ]
00007f9959c63000   10240      16      16 rw---    [ anon ]
00007f995a663000       4       0       0 -----    [ anon ]
00007f995a664000   10240       8       8 rw---    [ anon ]
00007f995b064000       4       0       0 -----    [ anon ]
00007f995b065000   10240       8       8 rw---    [ anon ]
00007f995ba65000       4       0       0 -----    [ anon ]
00007f995ba66000   10240       8       8 rw---    [ anon ]
00007f995c466000       4       0       0 -----    [ anon ]
00007f995c467000   12308     752     752 rw---    [ anon ]
00007f995d083000       4       0       0 -----    [ anon ]
00007f995d084000     192       0       0 rw---    [ anon ]
00007f995d0b4000       4       0       0 -----    [ anon ]
00007f995d0b5000     192      60      60 rw---    [ anon ]
00007f995d0e5000       4       0       0 -----    [ anon ]
00007f995d0e6000     192       0       0 rw---    [ anon ]
00007f995d116000       4       0       0 -----    [ anon ]
00007f995d117000     192       0       0 rw---    [ anon ]
00007f995d147000       4       0       0 -----    [ anon ]
00007f995d148000     192       0       0 rw---    [ anon ]
00007f995d178000       4       0       0 -----    [ anon ]
00007f995d179000     192       0       0 rw---    [ anon ]
00007f995d1a9000       4       0       0 -----    [ anon ]
00007f995d1aa000     192      60      60 rw---    [ anon ]
00007f995d1da000       4       0       0 -----    [ anon ]
00007f995d1db000     192       0       0 rw---    [ anon ]
00007f995d20b000       4       0       0 -----    [ anon ]
00007f995d20c000     192       0       0 rw---    [ anon ]
00007f995d23c000       4       0       0 -----    [ anon ]
00007f995d23d000     192       0       0 rw---    [ anon ]
00007f995d26d000       4       0       0 -----    [ anon ]
00007f995d26e000   10240       8       8 rw---    [ anon ]
00007f995dc6e000       4       0       0 -----    [ anon ]
00007f995dc6f000   10240       8       8 rw---    [ anon ]
00007f995e66f000       4       0       0 -----    [ anon ]
00007f995e670000   10240       8       8 rw---    [ anon ]
00007f995f070000       4       0       0 -----    [ anon ]
00007f995f071000   10240       8       8 rw---    [ anon ]
00007f995fa71000       4       0       0 -----    [ anon ]
00007f995fa72000   10240       4       4 rw---    [ anon ]
00007f9960472000       4       0       0 -----    [ anon ]
00007f9960473000   10240       4       4 rw---    [ anon ]
00007f9960e73000       4       0       0 -----    [ anon ]
00007f9960e74000   10240       4       4 rw---    [ anon ]
00007f9961874000       4       0       0 -----    [ anon ]
00007f9961875000   10240      12      12 rw---    [ anon ]
00007f9962275000       4       0       0 -----    [ anon ]
00007f9962276000   55200   21860   21860 rw---    [ anon ]
00007f996585e000      44       0       0 r-x--  libnss_files-2.13.so
00007f9965869000    2044       0       0 -----  libnss_files-2.13.so
00007f9965a68000       4       0       0 r----  libnss_files-2.13.so
00007f9965a69000       4       0       0 rw---  libnss_files-2.13.so
00007f9965a6a000      40       0       0 r-x--  libnss_nis-2.13.so
00007f9965a74000    2044       0       0 -----  libnss_nis-2.13.so
00007f9965c73000       4       0       0 r----  libnss_nis-2.13.so
00007f9965c74000       4       0       0 rw---  libnss_nis-2.13.so
00007f9965c75000      28       8       0 r-x--  libnss_compat-2.13.so
00007f9965c7c000    2044       0       0 -----  libnss_compat-2.13.so
00007f9965e7b000       4       0       0 r----  libnss_compat-2.13.so
00007f9965e7c000       4       0       0 rw---  libnss_compat-2.13.so
00007f9965e7d000       4       0       0 -----    [ anon ]
00007f9965e7e000   10240       4       4 rw---    [ anon ]
00007f996687e000      84       4       0 r-x--  libnsl-2.13.so
00007f9966893000    2044       0       0 -----  libnsl-2.13.so
00007f9966a92000       4       0       0 r----  libnsl-2.13.so
00007f9966a93000       4       0       0 rw---  libnsl-2.13.so
00007f9966a94000       8       0       0 rw---    [ anon ]
00007f9966a96000    1552     444       0 r-x--  libc-2.13.so
00007f9966c1a000    2044       0       0 -----  libc-2.13.so
00007f9966e19000      16       4       4 r----  libc-2.13.so
00007f9966e1d000       4       4       4 rw---  libc-2.13.so
00007f9966e1e000      20      12      12 rw---    [ anon ]
00007f9966e23000      84      12       0 r-x--  libgcc_s.so.1
00007f9966e38000    2048       0       0 -----  libgcc_s.so.1
00007f9967038000       4       0       0 rw---  libgcc_s.so.1
00007f9967039000     516      16       0 r-x--  libm-2.13.so
00007f99670ba000    2044       0       0 -----  libm-2.13.so
00007f99672b9000       4       0       0 r----  libm-2.13.so
00007f99672ba000       4       0       0 rw---  libm-2.13.so
00007f99672bb000     928      16       0 r-x--  libstdc++.so.6.0.17
00007f99673a3000    2048       0       0 -----  libstdc++.so.6.0.17
00007f99675a3000      32       0       0 r----  libstdc++.so.6.0.17
00007f99675ab000       8       4       4 rw---  libstdc++.so.6.0.17
00007f99675ad000      84       0       0 rw---    [ anon ]
00007f99675c2000       8       4       0 r-x--  libdl-2.13.so
00007f99675c4000    2048       0       0 -----  libdl-2.13.so
00007f99677c4000       4       0       0 r----  libdl-2.13.so
00007f99677c5000       4       0       0 rw---  libdl-2.13.so
00007f99677c6000      32       4       0 r-x--  libcrypt-2.13.so
00007f99677ce000    2044       0       0 -----  libcrypt-2.13.so
00007f99679cd000       4       0       0 r----  libcrypt-2.13.so
00007f99679ce000       4       0       0 rw---  libcrypt-2.13.so
00007f99679cf000     184       0       0 rw---    [ anon ]
00007f99679fd000      36       0       0 r-x--  libwrap.so.0.7.6
00007f9967a06000    2044       0       0 -----  libwrap.so.0.7.6
00007f9967c05000       4       0       0 r----  libwrap.so.0.7.6
00007f9967c06000       4       0       0 rw---  libwrap.so.0.7.6
00007f9967c07000       4       0       0 rw---    [ anon ]
00007f9967c08000      28       8       0 r-x--  librt-2.13.so
00007f9967c0f000    2044       0       0 -----  librt-2.13.so
00007f9967e0e000       4       4       4 r----  librt-2.13.so
00007f9967e0f000       4       0       0 rw---  librt-2.13.so
00007f9967e10000      88       8       0 r-x--  libz.so.1.2.7
00007f9967e26000    2044       0       0 -----  libz.so.1.2.7
00007f9968025000       4       0       0 r----  libz.so.1.2.7
00007f9968026000       4       0       0 rw---  libz.so.1.2.7
00007f9968027000       4       4       0 r-x--  libaio.so.1.0.1
00007f9968028000    2044       0       0 -----  libaio.so.1.0.1
00007f9968227000       4       0       0 r----  libaio.so.1.0.1
00007f9968228000       4       0       0 rw---  libaio.so.1.0.1
00007f9968229000      92      52       0 r-x--  libpthread-2.13.so
00007f9968240000    2044       0       0 -----  libpthread-2.13.so
00007f996843f000       4       4       4 r----  libpthread-2.13.so
00007f9968440000       4       4       4 rw---  libpthread-2.13.so
00007f9968441000      16       4       4 rw---    [ anon ]
00007f9968445000     128      44       0 r-x--  ld-2.13.so
00007f996846b000       4       0       0 -----    [ anon ]
00007f996846c000     192      60      60 rw---    [ anon ]
00007f996849c000       4       0       0 -----    [ anon ]
00007f996849d000     192      60      60 rw---    [ anon ]
00007f99684cd000       4       0       0 -----    [ anon ]
00007f99684ce000     192       0       0 rw---    [ anon ]
00007f99684fe000       4       0       0 -----    [ anon ]
00007f99684ff000     192       0       0 rw---    [ anon ]
00007f996852f000       4       0       0 -----    [ anon ]
00007f9968530000     192      60      60 rw---    [ anon ]
00007f9968560000       4       0       0 -----    [ anon ]
00007f9968561000     192       0       0 rw---    [ anon ]
00007f9968591000       4       0       0 -----    [ anon ]
00007f9968592000     192       0       0 rw---    [ anon ]
00007f99685c2000       4       0       0 -----    [ anon ]
00007f99685c3000     192       0       0 rw---    [ anon ]
00007f99685f3000       4       0       0 -----    [ anon ]
00007f99685f4000     192       0       0 rw---    [ anon ]
00007f9968624000       4       0       0 -----    [ anon ]
00007f9968625000     224       4       4 rw---    [ anon ]
00007f9968661000      12       0       0 rw---    [ anon ]
00007f9968664000       4       4       4 r----  ld-2.13.so
00007f9968665000       4       0       0 rw---  ld-2.13.so
00007f9968666000       4       0       0 rw---    [ anon ]
00007f9968667000   10732    3176       0 r-x--  mysqld
00007f99692e2000     460     196     196 r----  mysqld
00007f9969355000     660     204     184 rw---  mysqld
00007f99693fa000     160      88      88 rw---    [ anon ]
00007f9969ba3000   13372    3156    3156 rw---    [ anon ]
00007ffcdb217000      84      12      12 rw---    [ stack ]
00007ffcdb29c000       8       4       0 r-x--    [ anon ]
ffffffffff600000       4       0       0 r-x--    [ anon ]
----------------  ------  ------  ------
total kB          598152   34192   30368

Con la opción -x se puede obtener la suma del espacio de memoria total, residente y dirty (páginas modificadas en memoria principal).

Al igual que en la salida de ps, RSS indica la cantidad de memoria residente, esto es, el tamaño que ocupan las páginas almacenadas en memoria física (frames).

Sino es posible acceder directamente al sistema de archivos /proc, que exporta estructuras de datos del kernel. Dentro del directorio correspondiente a cada proceso existe el archivo status, el cual contiene información de estado del proceso incluyendo el uso de memoria virtual, memoria física (principal) y secundaria (swap):

root@linuxito:~# grep Vm /proc/23778/status
VmPeak:   598152 kB
VmSize:   598152 kB
VmLck:         0 kB
VmHWM:     60908 kB
VmRSS:     34436 kB
VmData:   551680 kB
VmStk:        88 kB
VmExe:     10732 kB
VmLib:      3692 kB
VmPTE:       360 kB
VmPTD:        16 kB
VmSwap:    36588 kB

Se observa que este proceso tiene la no despreciable cifra de casi 36 MB en memoria secundaria, lo cual puede ser malo para su rendimiento.

Referencias

man atop
man ps
man pmap

What is Overcommit? And why is it bad?

Out Of Memory Management

vm.overcommit_accounting


Tal vez pueda interesarte


Compartí este artículo