Determinar correctamente el uso de memoria en Linux

Determinar correctamente el uso de memoria en Linux

Estoy un poco confundido sobre algunos de los resultados que estoy viendoPDygratis.

En mi servidor, este es el resultado defree -m

[root@server ~]# free -m
             total       used       free     shared    buffers     cached
Mem:          2048       2033         14          0         73       1398
-/+ buffers/cache:        561       1486
Swap:         2047         11       2036

Según tengo entendido, cómo Linux administra la memoria es que almacenará el uso del disco en la RAM, de modo que cada acceso posterior sea más rápido. Creo que esto lo indican las columnas "en caché". Además, se almacenan varios búferes en la RAM, como se indica en la columna "búferes".

Entonces, si entiendo correctamente, se supone que el uso "real" es el valor "usado" de "-/+ buffers/cache", o 561 en este caso.

Entonces, suponiendo que todo eso sea correcto, la parte que me desconcierta son los resultados de ps aux.

Según tengo entendido ps, los resultados son que la sexta columna (RSS) representa el tamaño en kilobytes que el proceso utiliza para la memoria.

Entonces, cuando ejecuto este comando:

[root@server ~]# ps aux | awk '{sum+=$6} END {print sum / 1024}'
1475.52

¿No debería el resultado ser la columna "usada" de "-/+ buffers/cache" de free -m?

Entonces, ¿cómo puedo determinar correctamente el uso de memoria de un proceso en Linux? Aparentemente mi lógica es defectuosa.

Respuesta1

Copiar/pegar descaradamente mi respuesta defallo del servidorjusto el otro día :-)

El sistema de memoria virtual de Linux no es tan simple. No puedes simplemente sumar todos los campos RSS y obtener el valor informado usedpor free. Hay muchas razones para esto, pero mencionaré algunas de las más importantes.

  • Cuando un proceso se bifurca, tanto el padre como el hijo se mostrarán con el mismo RSS. Sin embargo, Linux emplea copia en escritura para que ambos procesos realmente utilicen la misma memoria. Sólo cuando uno de los procesos modifique la memoria, esta realmente se duplicará.
    Esto hará que el freenúmero sea menor que la topsuma RSS.

  • El valor RSS no incluye la memoria compartida. Debido a que la memoria compartida no es propiedad de ningún proceso, topno la incluye en RSS.
    Esto hará que el freenúmero sea mayor que la topsuma RSS.

Hay muchas otras razones por las que las cifras podrían no cuadrar. Esta respuesta solo intenta señalar que la administración de la memoria es muy compleja y que no se pueden simplemente sumar/restar valores individuales para obtener el uso total de la memoria.

Respuesta2

Si está buscando números de memoria que sumen, eche un vistazo asmem:

smem es una herramienta que puede brindar numerosos informes sobre el uso de memoria en sistemas Linux. A diferencia de las herramientas existentes, smem puede informar el tamaño de conjunto proporcional (PSS), que es una representación más significativa de la cantidad de memoria utilizada por bibliotecas y aplicaciones en un sistema de memoria virtual.

Debido a que grandes porciones de memoria física generalmente se comparten entre múltiples aplicaciones, la medida estándar de uso de memoria conocida como tamaño de conjunto residente (RSS) sobreestimará significativamente el uso de memoria. En cambio, PSS mide la "participación justa" de cada aplicación en cada área compartida para dar una medida realista.

Por ejemplo aquí:

# smem -t
  PID User     Command                         Swap      USS      PSS      RSS
...
10593 root     /usr/lib/chromium-browser/c        0    22868    26439    49364 
11500 root     /usr/lib/chromium-browser/c        0    22612    26486    49732 
10474 browser  /usr/lib/chromium-browser/c        0    39232    43806    61560 
 7777 user     /usr/lib/thunderbird/thunde        0    89652    91118   102756 
-------------------------------------------------------------------------------
  118 4                                       40364   594228   653873  1153092 

También lo PSSes la columna interesante aquí porque tiene en cuenta la memoria compartida.
A diferencia de RSSlo significativo que es sumarlo. Aquí obtenemos un total de 654 MB para procesos en el espacio de usuario.

La salida de todo el sistema informa sobre el resto:

# smem -tw
Area                           Used      Cache   Noncache 
firmware/hardware                 0          0          0 
kernel image                      0          0          0 
kernel dynamic memory        345784     297092      48692 
userspace memory             654056     181076     472980 
free memory                   15828      15828          0 
----------------------------------------------------------
                            1015668     493996     521672 

Entonces, 1 Gb de RAM en total = 654 Mb de procesos en el área de usuario + 346 Mb de memoria del kernel + 16 Mb libres
(más o menos unos pocos Mb)

En general, aproximadamente la mitad de la memoria se utiliza para caché (494 Mb).

Pregunta extra: ¿Qué es aquí el caché del área de usuario versus el caché del kernel?


Por cierto, prueba algo visual:

# smem  --pie=name

ingrese la descripción de la imagen aquí

Respuesta3

Una herramienta realmente buena es pmapla que enumera el uso actual de memoria para un determinado proceso:

pmap -d PID

Para obtener más información al respecto, consulte la página de manual man pmapy también eche un vistazo a20 herramientas de monitoreo del sistema Linux que todo administrador de sistemas debería conocer, que enumera excelentes herramientas que siempre uso para obtener información sobre mi sistema Linux.

Respuesta4

Como otros han señalado correctamente, es difícil controlar la memoria real utilizada por un proceso, con regiones compartidas, archivos mmap y todo eso.

Si eres un experimentador, puedes ejecutarvalgrind y macizo. Esto puede resultar un poco complicado para el usuario ocasional, pero podrá hacerse una idea del comportamiento de la memoria de una aplicación con el tiempo. Si una aplicación malloc() es exactamente lo que necesita, esto le dará una buena representación del uso real de memoria dinámica de un proceso. Pero este experimento puede ser "envenenado".

Para complicar las cosas, Linux le permitecomprometerse demasiadotu memoria. Cuando malloc() memoria, estás indicando tu intención de consumir memoria. Pero la asignación no ocurre realmente hasta que escribes un byte en una nueva página de tu "RAM" asignada. Puedes comprobarlo tú mismo escribiendo y ejecutando un pequeño programa en C como este:

// test.c
#include <malloc.h>
#include <stdio.h>
#include <unistd.h>
int main() {
    void *p;
    sleep(5)
    p = malloc(16ULL*1024*1024*1024);
    printf("p = %p\n", p);
    sleep(30);
    return 0;
}

# Shell:
cc test.c -o test && ./test &
top -p $!

Ejecute esto en una máquina con menos de 16 GB de RAM y, ¡listo!, ¡acaba de obtener 16 GB de memoria! (no en realidad no).

Observe que topve "VIRT" como 16.004G pero %MEM es 0.0

Ejecute esto nuevamente con valgrind:

# Shell:
valgrind --tool=massif ./test &
sleep 36
ms_print massif.out.$! | head -n 30

Y el macizo dice "suma de todas las asignaciones() = 16 GB". Entonces eso no es muy interesante.

PERO, si lo ejecutas en uncuerdoproceso:

# Shell:
rm test test.o
valgrind --tool=massif cc test.c -o test &
sleep 3
ms_print massif.out.$! | head -n 30

--------------------------------------------------------------------------------
Command:            cc test.c -o test
Massif arguments:   (none)
ms_print arguments: massif.out.23988
--------------------------------------------------------------------------------


    KB
77.33^                                                                       :
     |                                                                      #:
     |                                                                :@::@:#:
     |                                                           :::::@@::@:#:
     |                                                         @:: :::@@::@:#:
     |                                                     ::::@:: :::@@::@:#:
     |                                             ::@:::@:::::@:: :::@@::@:#:
     |                                            @::@:::@:::::@:: :::@@::@:#:
     |                                            @::@:::@:::::@:: :::@@::@:#:
     |                      :@@@@@@@@@@@@@@@@@@@@:@::@:::@:::::@:: :::@@::@:#:
     |                      :@@                  :@::@:::@:::::@:: :::@@::@:#:
     |                    :@:@@                  :@::@:::@:::::@:: :::@@::@:#:
     |                    :@:@@                  :@::@:::@:::::@:: :::@@::@:#:
     |                   :@@:@@                  :@::@:::@:::::@:: :::@@::@:#:
     |                   :@@:@@                  :@::@:::@:::::@:: :::@@::@:#:
     |              :@::::@@:@@                  :@::@:::@:::::@:: :::@@::@:#:
     |          :::::@::::@@:@@                  :@::@:::@:::::@:: :::@@::@:#:
     |        :::::::@::::@@:@@                  :@::@:::@:::::@:: :::@@::@:#:
     |       ::::::::@::::@@:@@                  :@::@:::@:::::@:: :::@@::@:#:
     |       ::::::::@::::@@:@@                  :@::@:::@:::::@:: :::@@::@:#:
   0 +----------------------------------------------------------------------->Mi
     0                                                                   1.140

Y aquí vemos (de forma muy empírica y con muy alta confianza) que el compilador asignó 77 KB de montón.

¿Por qué esforzarse tanto en conseguir solo un uso dinámico? Porque todos los objetos compartidos y secciones de texto que utiliza un proceso (en este ejemplo, el compilador) no son muy interesantes. Son una sobrecarga constante para un proceso. De hecho, las invocaciones posteriores del proceso casi son "gratuitas".

Además, compare y contraste lo siguiente:

MMAP() un archivo de 1GB. Su VMSize será 1+GB. Pero su tamaño de conjunto residente solo serán las partes del archivo en las que hizo que se paginaran (desreferenciando un puntero a esa región). Y si "lee" el archivo completo, cuando llegue al final, es posible que el kernel ya haya paginado el principio (esto es fácil de hacer porque el kernel sabe exactamente cómo y dónde reemplazar esas páginas si se desreferencian nuevamente). ). En cualquier caso, ni VMSize ni RSS son un buen indicador del "uso" de su memoria. En realidad, no has malloc()'ed nada.

Por el contrario, Malloc() y toque MUCHA memoria, hasta que su memoria se intercambie al disco. Entonces su memoria asignada ahora excede su RSS. Aquí, su VMSize podría comenzar a decirle algo (su proceso posee más memoria de la que realmente reside en su RAM). Pero todavía es difícil diferenciar entre VM que son páginas compartidas y VM que son datos intercambiados.

Aquí es donde valgrind/massif se vuelve interesante. Te muestra lo que tienesintencionalmenteasignados (independientemente del estado de sus páginas).

información relacionada