2008-09-22 9 views
36

Herramientas como 'ps' y 'top' reportan varios tipos de usos de memoria, como el tamaño de VM y el tamaño de conjunto residente. Sin embargo, ninguno de ellos es el uso de la memoria "real":¿Una forma de determinar el uso de memoria "real" de un proceso, es decir, un RSS sucio privado?

  • El código del programa se comparte entre varias instancias del mismo programa.
  • El código del programa de biblioteca compartida se comparte entre todos los procesos que usan esa biblioteca.
  • Algunas aplicaciones separan los procesos y comparten memoria con ellos (por ejemplo, a través de segmentos de memoria compartida).
  • El sistema de memoria virtual hace que el informe de tamaño de VM sea prácticamente inútil.
  • RSS es 0 cuando se intercambia un proceso, por lo que no es muy útil.
  • , etc, etc

que he encontrado que la RSS sucia privada, según lo informado por Linux, es lo más parecido a la utilización de la memoria "real". Esto se puede obtener sumando todos los valores Private_Dirty en /proc/somepid/smaps.

Sin embargo, ¿otros sistemas operativos proporcionan una funcionalidad similar? si no, cuales son las alternativas? En particular, estoy interesado en FreeBSD y OS X.

+0

¿Qué es exactamente el "uso de memoria real"? Según su lista, la idea del uso de memoria para un único proceso es inútil o arbitraria. – BCS

+2

Definiría "uso de memoria real" como la cantidad de memoria física (pero no de intercambio) que se liberaría si 'mato -9' el proceso dado. Creo que ese número debería estar entre los valores RSS y PSS informados para un proceso. –

+0

@Hongli: Aunque es un hilo viejo, me sorprende que el montaje de linprocfs no formara parte de la solución sugerida por cualquiera aquí, para FreeBSD. ¿Hay alguna razón específica para lo mismo? . De todos modos, he agregado esa respuesta por el bien de completarla. – Arvind

Respuesta

3

Top sabe cómo hacer esto. Muestra VIRT, RES y SHR por defecto en Debian Linux. VIRT = SWAP + RES. RES = CÓDIGO + DATOS. SHR es la memoria que se puede compartir con otro proceso (biblioteca compartida u otra memoria).

Además, la memoria "sucia" es meramente memoria RES que se ha utilizado y/o no se ha intercambiado.

Puede ser difícil de decir, pero la mejor manera de entenderlo es observar un sistema que no se está intercambiando. Entonces, RES - SHR es la memoria exclusiva del proceso. Sin embargo, esa no es una buena manera de verlo, porque no sabe que la memoria en SHR está siendo utilizada por otro proceso. Puede representar páginas de objetos compartidos no escritas que solo utiliza el proceso.

+0

No creo que sea correcto. Considere http://pastie.org/277766 Esto asigna 300 MB al espacio de direcciones, pero solo se escribe el último byte. El uso de la memoria real para ese bloque debe ser de 4 KB (tamaño de una página). El uso real de la memoria de proceso solo debe ser de varios KB. – Hongli

+0

Cualquier memoria no utilizada en su ejemplo aún aparecería en el total de VIRT. Y el total de RES reflejaría cualquier memoria no utilizada (es decir, no la mostrará). Al menos, así parece funcionar en Debian x86. – Chris

+0

Estoy de acuerdo con usted. RES-SHR será una buena forma de evaluar el uso de memoria de proceso para la mayoría de los procesos. Por lo general, las pérdidas de memoria ocurren en la memoria privada y eso es lo que investigará. Si uno quiere saber el uso de la memoria completa, no debe resumir los procesos, sino ir a top/htop en general. – norekhov

4

Realmente no se puede.

Quiero decir, memoria compartida entre procesos ... ¿vas a contarlo o no? Si no lo cuentas, estás equivocado; la suma del uso de la memoria de todos los procesos no va a ser el uso total de la memoria. Si lo cuenta, lo contará dos veces; la suma no será correcta.

Yo, estoy contento con RSS. Y sabiendo que en realidad no puede confiar plenamente en él ...

35

En OSX, el Monitor de actividad realmente le da una buena idea.

La memoria privada es segura para la memoria que solo utiliza su aplicación. P.ej. la memoria de pila y toda la memoria reservada dinámicamente utilizando malloc() y funciones/métodos comparables (método alloc para Objective-C) es memoria privada. Si se bifurca, la memoria privada se compartirá con su hijo, pero se marcará como copiar y escribir. Eso significa que mientras una página no sea modificada por ninguno de los procesos (padre o hijo) se compartirá entre ellos. Tan pronto como cualquiera de los procesos modifica cualquier página, esta se copia antes de que se modifique. Aunque esta memoria se comparte con los hijos de la horquilla (y puede solo ser compartida con los niños de la horquilla), todavía se muestra como memoria "privada", porque en el peor de los casos, cada página se modificará (tarde o temprano) y luego vuelve a ser privado para cada proceso nuevamente.

La memoria compartida es memoria compartida actualmente (las mismas páginas son visibles en el espacio de proceso virtual de diferentes procesos) o es probable que se comparta en el futuro (por ejemplo, memoria de solo lectura, ya que no hay razón por no compartir memoria de solo lectura). Al menos así es como leo el código fuente de algunas herramientas de línea de comando de Apple. Entonces, si comparte memoria entre procesos usando mmap (o una llamada comparable que mapea la misma memoria en múltiples procesos), esto sería memoria compartida. Sin embargo, el código ejecutable también es memoria compartida, ya que si se inicia otra instancia de su aplicación no hay ninguna razón por la cual no pueda compartir el código ya cargado en la memoria (las páginas de códigos ejecutables son de solo lectura por defecto, a menos que esté ejecutando aplicación en un depurador). Por lo tanto, la memoria compartida es realmente utilizada por la aplicación, al igual que la privada, pero también puede compartirse con otro proceso (o no, pero ¿por qué no se contabilizaría en su aplicación si se compartió?)

La memoria real es la cantidad de RAM actualmente "asignada" a su proceso, no importa si es privada o compartida. Esto puede ser exactamente la suma de privado y compartido, pero generalmente no lo es. Es posible que su proceso tenga más memoria asignada de la que necesita actualmente (esto acelera las solicitudes de más memoria en el futuro), pero eso no representa ninguna pérdida para el sistema. Si otro proceso necesita memoria y no hay memoria libre disponible, antes de que el sistema comience a intercambiar, quitará esa memoria adicional de su proceso y le asignará otro proceso (que es una operación rápida e indolora); por lo tanto, su próxima llamada malloc podría ser algo más lenta. La memoria real también puede ser más pequeña que la memoria privada y física; esto se debe a que si su proceso solicita memoria del sistema, solo recibirá "memoria virtual". Esta memoria virtual no está vinculada a ninguna página de memoria real, siempre y cuando no la utilice (por lo tanto, malloc 10 MB de memoria, use solo un byte de ella, su proceso obtendrá solo una página, 4096 byte, de memoria asignada - el resto solo se asigna si alguna vez lo necesitas). La memoria adicional que se intercambia puede no contar también para la memoria real (no estoy seguro de esto), pero contará para la memoria compartida y privada.

La memoria virtual es la suma de todos los bloques de direcciones que se consideran válidos en el espacio de proceso de sus aplicaciones. Estas direcciones pueden estar vinculadas a la memoria física (que de nuevo es privada o compartida) o no, pero en ese caso se vincularán a la memoria física tan pronto como utilice la dirección. Acceder a direcciones de memoria fuera de las direcciones conocidas causará un SIGBUS y su aplicación se bloqueará. Cuando se cambia la memoria, el espacio de direcciones virtuales para esta memoria sigue siendo válido y el acceso a esas direcciones hace que la memoria se va a intercambiar de nuevo en

Conclusión:.
Si su aplicación no explícita o implícitamente el uso de memoria compartida, memoria privada es la cantidad de memoria que su aplicación necesita debido al tamaño de la pila (o tamaños si son multiproceso) y debido a las llamadas malloc() que realizó para la memoria dinámica. No tiene que preocuparse mucho por la memoria compartida o real en ese caso.

Si su aplicación utiliza memoria compartida, y esto incluye una interfaz gráfica de usuario, donde la memoria se comparte entre su aplicación y el WindowServer, por ejemplo, entonces también puede echar un vistazo a la memoria compartida. Un número de memoria compartido muy alto puede significar que tiene demasiados recursos gráficos cargados en la memoria en este momento.

La memoria real es de poco interés para el desarrollo de aplicaciones. Si es más grande que la suma de compartido y privado, entonces esto no significa nada más que el hecho de que el sistema es perezoso en la memoria alejada de su proceso. Si es más pequeño, entonces su proceso ha solicitado más memoria de la que realmente necesitaba, lo cual tampoco está mal, ya que mientras no use toda la memoria solicitada, no estará "robando" la memoria del sistema.Si es mucho más pequeño que la suma de compartido y privado, solo puede considerar solicitar menos memoria cuando sea posible, ya que está solicitando un poco más de memoria (una vez más, esto no está mal, pero me dice que su código no es optimizado para un uso mínimo de memoria y si es multiplataforma, otras plataformas pueden no tener un manejo de memoria tan sofisticado, por lo que puede preferir asignar muchos bloques pequeños en lugar de algunos grandes, por ejemplo, o liberar memoria mucho antes, y así en).

Si aún no está satisfecho con toda esa información, puede obtener aún más información. Abra una terminal y ejecute:

sudo vmmap <pid> 

donde está la identificación del proceso de su proceso. Esto le mostrará estadísticas para CADA bloque de memoria en su espacio de proceso con dirección inicial y final. También le indicará de dónde proviene este recuerdo (¿Un archivo mapeado? ¿Memoria de pila? ¿Memoria Malloc? ¿Una sección __DATA o __TEXT de su ejecutable?), Qué tan grande es en KB, los derechos de acceso y si es privado, compartido o copiado sobre escritura. Si se mapea desde un archivo, incluso le dará la ruta al archivo.

Si desea que sólo el uso de RAM "real", utilice

sudo vmmap -resident <pid> 

Ahora se mostrará para cada bloque de memoria el tamaño del bloque de memoria es virtualmente y cuánto de realidad es actualmente presentes en la memoria física.

Al final de cada volcado también hay una tabla de resumen con las sumas de diferentes tipos de memoria. Esta tabla se ve así para Firefox ahora mismo en mi sistema:

REGION TYPE    [ VIRTUAL/RESIDENT] 
===========    [ =======/========] 
ATS (font support)  [ 33.8M/ 2496K] 
CG backing stores  [ 5588K/ 5460K] 
CG image    [  20K/  20K] 
CG raster data   [ 576K/ 576K] 
CG shared images  [ 2572K/ 2404K] 
Carbon     [ 1516K/ 1516K] 
CoreGraphics   [  8K/  8K] 
IOKit     [ 256.0M/  0K] 
MALLOC     [ 256.9M/ 247.2M] 
Memory tag=240   [  4K/  4K] 
Memory tag=242   [  12K/  12K] 
Memory tag=243   [  8K/  8K] 
Memory tag=249   [ 156K/  76K] 
STACK GUARD    [ 101.2M/ 9908K] 
Stack     [ 14.0M/ 248K] 
VM_ALLOCATE    [ 25.9M/ 25.6M] 
__DATA     [ 6752K/ 3808K] 
__DATA/__OBJC   [  28K/  28K] 
__IMAGE     [ 1240K/ 112K] 
__IMPORT    [ 104K/ 104K] 
__LINKEDIT    [ 30.7M/ 3184K] 
__OBJC     [ 1388K/ 1336K] 
__OBJC/__DATA   [  72K/  72K] 
__PAGEZERO    [  4K/  0K] 
__TEXT     [ 108.6M/ 63.5M] 
__UNICODE    [ 536K/ 512K] 
mapped file    [ 118.8M/ 50.8M] 
shared memory   [ 300K/ 276K] 
shared pmap    [ 6396K/ 3120K] 

¿Qué nos dice esto? P.ej. el binario de Firefox y toda la biblioteca que carga tienen 108 MB de datos juntos en sus secciones __TEXT, pero actualmente solo 63 MB de ellos residen actualmente en la memoria. El soporte de fuentes (ATS) necesita 33 MB, pero solo unos 2,5 MB están realmente en la memoria. Utiliza un poco más de 5 MB de copias de respaldo CG, CG = Núcleo de gráficos, esos son más probable contenido de ventana, botones, imágenes y otros datos que se almacenan en caché para un dibujo rápido. Ha solicitado 256 MB a través de llamadas malloc y actualmente 247 MB ​​están realmente asignados a páginas de memoria. Tiene 14 MB de espacio reservado para las pilas, pero solo el espacio de la pila de 248 KB realmente está en uso en este momento.

VMMap también tiene un buen resumen sobre la mesa

ReadOnly portion of Libraries: Total=139.3M resident=66.6M(48%) swapped_out_or_unallocated=72.7M(52%) 
Writable regions: Total=595.4M written=201.8M(34%) resident=283.1M(48%) swapped_out=0K(0%) unallocated=312.3M(52%) 

Y esto muestra un aspecto interesante de la OS X: Para memoria de sólo lectura que no juega ningún papel si se intercambia o simplemente no asignado; solo hay residente y no residente. Para la memoria grabable esto hace una diferencia (en mi caso el 52% de toda la memoria solicitada nunca se ha utilizado y está sin asignar, el 0% de la memoria se ha intercambiado en el disco)

8

En Linux, es posible que desee el PSS (números de tamaño proporcional) en/proc/self/smaps. El PSS de un mapeo es su RSS dividido por el número de procesos que usan ese mapeo.

4

Puede obtener RSS limpio sucio y privada en privado desde/proc/PID/smaps

0

Por una cuestión que se menciona FreeBSD, no sorprendió a nadie escribió esto todavía:

si quieres un estilo de Linux/proc/salida/estado ProcessId, por favor haga lo siguiente:

mount -t linprocfs none /proc 
cat /proc/PROCESSID/status 

al menos en FreeBSD 7.0, el montaje no se ha hecho de forma predeterminada (7.0 es una versión mucho más antigua, pero para algo tan básico, la respuesta estaba oculto en una lista de correo!)

1
for i in /proc/[0-9]*; do 
    grep -q 'Private_Dirty' $i/smaps; 
    if [ $? -ne 0 ]; then 
    continue; 
    fi; 
    echo -n "${i}: "; 
    awk '/Private_Dirty/ {print $2,$3}' $i/smaps | 
    sed 's/ tB/*1024 gB/;s/ gB/*1024 mB/;s/ mB/*1024 kB/;s/ kB/*1024/;1!s/^/+/;' | 
    tr -d '\n' | 
    sed 's/$/\n/' | 
    bc | 
    tr -d '\n'; 
    echo; 
done | 
sort -n -k 2 
0

Compruébelo usted mismo, este es el código fuente de gnome-system-monitor, se piensa que la memoria "realmente utilizado" por un solo proceso es la suma (info->mem) de memoria del servidor X (info->memxserver) y memoria se puede escribir (info->memwritable), el "grabable memoria" es los bloques de memoria que están marcados como "Private_Dirty" en el archivo /proc/PID/smaps.

Aparte del sistema de Linux, podría ser de otra manera según el código gnome-system-monitor.

static void 
get_process_memory_writable (ProcInfo *info) 
{ 
    glibtop_proc_map buf; 
    glibtop_map_entry *maps; 

    maps = glibtop_get_proc_map(&buf, info->pid); 

    gulong memwritable = 0; 
    const unsigned number = buf.number; 

    for (unsigned i = 0; i < number; ++i) { 
#ifdef __linux__ 
     memwritable += maps[i].private_dirty; 
#else 
     if (maps[i].perm & GLIBTOP_MAP_PERM_WRITE) 
      memwritable += maps[i].size; 
#endif 
    } 

    info->memwritable = memwritable; 

    g_free(maps); 
} 

static void 
get_process_memory_info (ProcInfo *info) 
{ 
    glibtop_proc_mem procmem; 
    WnckResourceUsage xresources; 

    wnck_pid_read_resource_usage (gdk_screen_get_display (gdk_screen_get_default()), 
            info->pid, 
            &xresources); 

    glibtop_get_proc_mem(&procmem, info->pid); 

    info->vmsize = procmem.vsize; 
    info->memres = procmem.resident; 
    info->memshared = procmem.share; 

    info->memxserver = xresources.total_bytes_estimate; 

    get_process_memory_writable(info); 

    // fake the smart memory column if writable is not available 
    info->mem = info->memxserver + (info->memwritable ? info->memwritable : info->memres); 
} 
Cuestiones relacionadas