2011-07-03 9 views
5

Estoy escribiendo una aplicación en C++ que utiliza algunas bibliotecas externas de código abierto. Traté de ver el Monitor del sistema Ubuntu para obtener información sobre cómo mi proceso usa recursos, y noté que la memoria residente continúa aumentando a valores muy grandes (más de 100MiB). Esta aplicación debe ejecutarse en un dispositivo integrado, así que tengo que tener cuidado.Ubuntu System Monitor y valgrind para descubrir fugas de memoria en aplicaciones C++

Empecé a pensar que debería haber una (alguna) pérdida de memoria, así que estoy usando valgrind. Desafortunadamente, parece que valgrind no está informando pérdidas de memoria significativas, solo algunos problemas menores en las bibliotecas que estoy usando, nada más.

Entonces, ¿tengo que concluir que mi algoritmo realmente usa tanta memoria? Me parece muy extraño ... ¿O tal vez estoy malinterpretando el significado de las columnas del Monitor del sistema? ¿Alguien puede aclarar el significado de "Memoria virtual", "Memoria residente", "Memoria grabable" y "Memoria" en el Monitor del sistema cuando se relaciona con el perfil del software? ¿Debería esperar que esos valores representen inmediatamente la cantidad de memoria que mi proceso está tomando en la memoria RAM?

En el pasado he usado herramientas que podían decirme dónde estaba usando la memoria, como Apple Profiling Tools. ¿Hay algo similar que pueda usar en Linux también?

Gracias!

Respuesta

6

Otra herramienta que puede probar es la /lib/libmemusage.so biblioteca: (. I Quit vim inmediatamente después del inicio)

$ LD_PRELOAD=/lib/libmemusage.so vim 

Memory usage summary: heap total: 4643025, heap peak: 997580, stack peak: 26160 
     total calls total memory failed calls 
malloc|  42346  4528378    0 
realloc|   52   7988    0 (nomove:26, dec:0, free:0) 
calloc|   34   106659    0 
    free|  28622  3720100 
Histogram for block sizes: 
    0-15   14226 33% ================================================== 
    16-31   8618 20% ============================== 
    32-47   1433 3% ===== 
    48-63   4174 9% ============== 
    64-79   4736 11% ================ 
    80-95   313 <1% = 
... 

Tal vez el histograma de los tamaños de bloque le dará suficiente información para saber dónde fugas puede estar sucediendo

valgrind es muy configurable; --leak-check=full --show-reachable=yes podría ser un buen punto de partida, si aún no lo ha probado.


"memoria virtual", "memoria residente", "Se puede escribir la memoria" y "memoria"

memoria virtual es el espacio de direcciones que su aplicación tiene asignado . Si ejecuta malloc(1024*1024*100);, la función de biblioteca malloc(3) solicitará 100 megabytes de almacenamiento del sistema operativo (o lo manejará fuera de las listas gratuitas). Los 100 megabytes se asignarán con mmap(..., MAP_ANONYMOUS), , que en realidad no asignarán ninguna memoria. (Consulte la descripción al final de la página malloc(3) para obtener más información). El SO proporcionará memoria la primera vez que se escriba cada página.

Las cuentas de memoria virtual para todas las bibliotecas y objetos ejecutables que se asignan en su proceso, así como su espacio de pila.

memoria residente es la cantidad de memoria que es en realidad en la memoria RAM. Puede vincular con toda la biblioteca de C de 1,5 megabytes, pero solo use los 100k (conjeturas descabelladas) de la biblioteca necesaria para admitir la interfaz de IO estándar. El resto de la biblioteca será demand paged desde el disco cuando sea necesario.O bien, si su sistema está bajo presión de memoria y algunos datos usados ​​menos recientemente están paginados para intercambiar, ya no contarán contra memoria residente.

La memoria que se puede escribir es la cantidad de espacio de direcciones que su proceso ha asignado con privilegios de escritura. (Consulte la salida del comando pmap(1): pmap $$ para el shell, por ejemplo, para ver qué páginas están asignadas a qué archivos, espacio anónimo, la pila y los privilegios en esas páginas.) Esta es una indicación razonable de cuánto espacio de intercambio el programa podría requerir en el peor de los casos el escenario de intercambio, cuando todo se debe paginar en el disco, o la cantidad de memoria que usa el proceso .

Como probablemente haya 50--100 procesos en su sistema a la vez, y casi todos ellos están vinculados con la biblioteca C estándar, todos los procesos obtienen comparten las asignaciones de memoria de solo lectura para la biblioteca . (También obtienen a compartir toda la copia en escritura grabable privada asignaciones para los archivos abiertos con mmap(..., MAP_PRIVATE|PROT_WRITE), hasta que el proceso se escribe en la memoria.) La herramienta top(1) informará la cantidad de memoria que puede ser compartido entre procesos en la columna SHR. (Tenga en cuenta que la memoria podría no ser compartida, pero algunos de ellos (libc) definitivamente es compartida.)

memoria es muy vaga. No sé lo que significa.

+0

Muchas gracias por la información. Tengo una pregunta con respecto a la memoria residente: ¿debo esperar que disminuya tan pronto como se desasigna (por ejemplo, con una eliminación o sin cargo), o debería esperar que flote de alguna otra manera? ¡Gracias! –

+0

@Luca, mientras que la memoria residente _can_ puede caer cuando un proceso 'free()' s es su memoria, el asignador de memoria _no_ podría devolver la memoria al sistema operativo. Si liberas un trozo grande (más grande que una página, tal vez mucho más grande), entonces podría esperar que el uso vuelva a bajar. Pero si libera objetos de una página más pequeños, incluso si libera muchos de ellos, no siempre esperaría que el tamaño del conjunto residente disminuya. – sarnold