2010-01-14 13 views
7

Estoy perfilando mi servidor retorcido. Utiliza mucha más memoria de la que esperaba. Su uso de memoria crece con el tiempo.El uso de memoria reportado por guppy difiere del comando ps

ps -o pid,rss,vsz,sz,size,command 
    PID RSS VSZ SZ SZ COMMAND 
7697 70856 102176 25544 88320 twistd -y broadcast.tac 

Como se puede ver que cuesta 102176 KBs, a saber, 99.78125 MBs. Y uso guppy de una boca de acceso retorcida para mirar el perfil de uso de la memoria.

>>> hp.heap() 
Partition of a set of 120537 objects. Total size = 10096636 bytes. 
Index Count %  Size % Cumulative % Kind (class/dict of class) 
    0 61145 51 5309736 53 5309736 53 str 
    1 27139 23 1031596 10 6341332 63 tuple 
    2 2138 2 541328 5 6882660 68 dict (no owner) 
    3 7190 6 488920 5 7371580 73 types.CodeType 
    4 325 0 436264 4 7807844 77 dict of module 
    5 7272 6 407232 4 8215076 81 function 
    6 574 0 305776 3 8520852 84 dict of class 
    7 605 1 263432 3 8784284 87 type 
    8 602 0 237200 2 9021484 89 dict of type 
    9 303 0 157560 2 9179044 91 dict of zope.interface.interface.Method 
<384 more rows. Type e.g. '_.more' to view.> 

Hum ... Parece que hay algo mal. Guppy muestra que el uso total de la memoria es 10096636 bytes, es decir, 9859.996 KBs o 9.628 MBs.

Eso es una gran diferencia. ¿Qué hay de malo en este extraño resultado? ¿Qué estoy haciendo mal?

Actualización: Escribí una secuencia de comandos del monitor anoche. Registra el uso de la memoria y la cantidad de usuarios en línea. Es un servidor de radio, por lo que puede ver que hay radios y oyentes totales. Aquí está la figura que generé por matplotlib. alt text http://static.ez2learn.com/temp/mem_figure.svg

Algo es extraño. A veces, el uso de la memoria impresa por ps es muy bajo, como este

2010-01-15 00:46:05,139 INFO 4 4 17904 36732 9183 25944 
2010-01-15 00:47:03,967 INFO 4 4 17916 36732 9183 25944 
2010-01-15 00:48:04,373 INFO 4 4 17916 36732 9183 25944 
2010-01-15 00:49:04,379 INFO 4 4 17916 36732 9183 25944 
2010-01-15 00:50:02,989 INFO 4 4 3700 5256 1314 2260 

Cuál es la razón del valor muy bajo de uso de la memoria? Y lo que es más, incluso si no hay radios en línea, no hay oyentes, el uso de la memoria sigue siendo alto.

Respuesta

6

posiblemente debido a intercambiar/reserva de memoria, basado en la definición de PS:

RSS: resident set size, the non-swapped physical memory 
    that a task has used (in kiloBytes). 

VSZ: virtual memory usage of entire process. 
    vm_lib + vm_exe + vm_data + vm_stack 

Puede ser un poco confuso, 4 métricas de diferentes tamaños se pueden ver con:

# ps -eo pid,vsz,rss,sz,size,cmd|egrep python 

PID VSZ RSS SZ SZ CMD 
23801 4920 2896 1230 1100 python 

el tamaño virtual incluye la memoria que el proceso reservó y no utilizó, el tamaño de todas las bibliotecas compartidas que se cargaron, las páginas que se intercambiaron y los bloques que ya fueron liberados por su proceso, por lo que podría ser mucho más grande que el tamaño de todos objetos en python.

algunas herramientas adicionales para investigar el rendimiento de memoria:

buena guía de localizar pérdidas de memoria en Python usando pdb y objgraph:

http://www.lshift.net/blog/2008/11/14/tracing-python-memory-leaks

+0

Pero incluso comparo 69 MB con 10MB, es demasiado lejos. ¿Cual podría ser el problema? Y lo que es más, el uso de memoria crece con el tiempo. Al principio, el RSS es de aproximadamente 2xMB, y ahora llega a 6x. –

+0

algunos de los objetos informados por guppy podrían intercambiarse para que python pueda informarlos, mientras que rss no lo incluiría ... no estoy seguro de por qué el proceso está reservando tanta memoria, quizás toneladas de librerías compartidas ...? – jspcal

+0

Todas las bibliotecas se cargan al inicio. Utiliza solo 2x MB en el campo RSS cuando se inicia el servidor. No tiene sentido que las bibliotecas ocupen más memoria. ¿Hay alguna manera de saber cuál es el uso de memoria invisible? –

3

Como se ha señalado anteriormente, el tamaño de RSS es lo que más te interesa aquí.El tamaño "virtual" incluye bibliotecas mapeadas, que probablemente no desee contar.

Ha pasado un tiempo desde que usé Heapy, pero estoy bastante seguro de que las estadísticas que imprime no incluyen los gastos generales agregados por Heapy. Esta sobrecarga puede ser bastante significativa (he visto un proceso RSS de 100 MB crecer una docena más o menos MB, ver http://www.pkgcore.org/trac/pkgcore/doc/dev-notes/heapy.rst).

Pero en su caso sospecho que el problema es que está utilizando alguna biblioteca C que o bien tiene pérdidas o usa memoria de una manera que heapy no rastrea. Heapy es consciente de la memoria utilizada directamente por los objetos de Python, pero si esos objetos envuelven objetos C que se asignan por separado, Heapy normalmente no está al tanto de esa memoria. Es posible que pueda agregar compatibilidad con Heapy a sus enlaces (pero si no controla los enlaces que usa, obviamente es una molestia, e incluso si controla los enlaces, es posible que no pueda hacer esto dependiendo de lo que esté envolviendo)

Si hay pérdidas en el nivel C, Heapy también perderá la pista de esa memoria (el tamaño de RSS aumentará, pero el tamaño informado de Heapy seguirá siendo el mismo). Valgrind es probablemente su mejor apuesta para rastrear estos, al igual que en otras aplicaciones C.

Finalmente: la fragmentación de la memoria a menudo hará que el uso de la memoria (como se ve en la parte superior) suba pero no baje (mucho). Esto no suele ser un gran problema con los daemons, ya que el proceso reutilizará esta memoria, simplemente no se libera en el sistema operativo, por lo que los valores en la parte superior no vuelven a bajar. Si el uso de la memoria (como se ve arriba) aumenta de forma más o menos lineal con la cantidad de usuarios (conexiones), no retrocede, pero tampoco crece para siempre hasta alcanzar un nuevo número máximo de usuarios, la fragmentación es probable culpar.

1

Esta no es una respuesta completa, pero desde su boca de acceso, también sugiero ejecutar gc.collect() manualmente antes de buscar con ps o top. guppy mostrará el montón asignado, pero no hace nada para liberar proactivamente los objetos que ya no están asignados.

Cuestiones relacionadas