Esta web utiliza cookies, puedes ver nuestra política de cookies, aquí Si continuas navegando estás aceptándola

Uso de memoria en Linux


La gestión de memoria en sistemas Linux es un proceso complicado, los datos ofrecidos por las herramientas del propio sistema operativo pueden llevarnos a una interpretación errónea.

Primero debemos tener claros algunos conceptos para entender la salida mostrada por el sistema operativo:

  • page: Bloque de memoria utilizado en la gestión de memoria por Linux. Un valor típico en Linux es de 4096bytes.
  • physical memory: Memoria RAM real, HW puro y duro.
  • virtual memory: Espacio de memoria mostrado a un proceso, este cree que es un espacio continuo y aislado del resto de memoria.

 

En teoria un proceso cuando carga debería de cargar todas las librerías necesarias para funcionar, pero en realidad esto no se hace, se carga lo necesario para arrancar y cuando necesita alguna librería la MMU(Memory Management Unit) pausa el proceso, carga la librería en la RAM y añade una referencia(mapea) en la memoria virtual del proceso correspondiente la dirección donde están los datos de la libreria.


Ps aux nos ofrece varios datos sobre la memoria RAM:

USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND

 

  • VSZ(virtual memory size): Memoria necesaria si el proceso necesita cargar TODAS las librerias con las que fué linkado.
  • RSS(Resident Set Size): Memoria real utilizada por el proceso, pero se debe tener en cuenta que aquí se están contando librerias compartidas entre procesos.


Hay otro valor que nos puede ser de utilidad:

  • PSS(Proportional Set Size): Este nos indica la memoria utilizada por el core del software, lo mínimo para arrancar y la n-esima parte de memoria utilizada por las librerias compartidas.

 

Si una libreria se comparte entre 3 procesos PSS mostrará lo que ocupe el core + (el tamaño de la librería/3)

Hay una herramienta que tiene en cuenta esto:

http://www.selenic.com/smem/

 

Instalamos las dependencias:

emerge -av dev-python/matplotlib

 

Clonamos por mercurial:

emerge -av dev-vcs/mercurial
cd /usr/src
hg clone http://selenic.com/repo/smem
cd smem
python2.7 smem

 

 PID User     Command                             Swap      USS      PSS      RSS
2254 XX     ck-launch-session dbus-laun        0      144      177      876

 

NOTA: Por si el repo de memoria dejo aquí la versión 1.4.

 

Otro aspecto a tener en cuenta es la fragmentación de memoria:

  • Interna: la memoria solo se puede asignar en valores divisibles por 4, 8 o 16 bytes, si se pide 23 te ofrecerá 24 con lo que ya hay un byte fragmentado.
  • Externa: es la memoria libre la que está fragmentada, si tenemos 3 fragmentos de 2 bytes y una app necesita 3 NO podremos cargar lo que necesita porque en ninguno de los espacios de forma independiente cabe.

 

Por ejemplo en Redis suele haber discordancia entre RSS y used_memory, RSS nos dará la ram utilizada por Redis contando los huecos de fragmentación mientras que used_memory de redis nos dará la RAM que realmente le es útil.

 

Mitigación de la fragmentación externa:

La RAM se compone de dos partes, Stack y Heap, esta asignación es semidinámica es decir se puede definir mediante ciertos parámetros de configuración del SO.

Si un variable es mas grande que un tipo primitivo se tendrá que utilizar malloc y en vez de almacenarla en la stack lo hará en la heap, de este modo quedará un puntero en la stack que apunta a la dirección de memoria en la heap.
Operando de este modo se pueden meter varios punteros en la stack que apunten a varias direcciones de la heap cuya suma conforme el valor de una variable evitando de este modo la fragmentación externa.

Se podría decir que la stack es el tamaño máximo de RAM que el SO nos permitirá utilizar para variables primitivas mientras que el heap es el resto de RAM.

Se puede ajustar el tamaño de la pila en el SO según el software que se vaya a correr:

  • Menos --> Pocas variables pero muy grandes
  • Mas --> Muchas variables pequeñas

 

NOTA: Las variables en stack son mas rápidas ya que no hace falta leer el puntero para acceder a los datos si no que lee el valor directamente.

 

Para definir el tamaño de la stack en Linux:

ulimit -a
stack size (kbytes, -s) 10240

Autor: Kr0m -- 27/02/2014 13:02:09