Recientemente me interesé en los algoritmos y comencé a explorarlos escribiendo una implementación ingenua y luego optimizándola de varias maneras.
Ya estoy familiarizado con el módulo estándar de Python para perfilar el tiempo de ejecución (para la mayoría de las cosas he encontrado que la función mágica timeit en IPython es suficiente), pero también estoy interesado en el uso de la memoria para poder explorar esas compensaciones también ( por ejemplo, el costo de almacenar en caché una tabla de valores calculados previamente versus volver a calcularlos según sea necesario). ¿Hay un módulo que perfile el uso de memoria de una función determinada para mí?
Respuestas:
Esto ya ha sido respondido aquí: generador de perfiles de memoria Python
Básicamente haces algo así (citado de Guppy-PE ):
fuente
Python 3.4 incluye un nuevo módulo:
tracemalloc
. Proporciona estadísticas detalladas sobre qué código está asignando la mayor cantidad de memoria. Aquí hay un ejemplo que muestra las tres líneas principales que asignan memoria.Y aquí están los resultados:
¿Cuándo es una pérdida de memoria no una pérdida?
Ese ejemplo es excelente cuando la memoria todavía se mantiene al final del cálculo, pero a veces tiene un código que asigna mucha memoria y luego lo libera todo. Técnicamente no es una pérdida de memoria, pero está usando más memoria de la que crees que debería. ¿Cómo puede rastrear el uso de la memoria cuando todo se libera? Si es su código, probablemente pueda agregar algún código de depuración para tomar instantáneas mientras se está ejecutando. De lo contrario, puede iniciar un subproceso en segundo plano para controlar el uso de la memoria mientras se ejecuta el subproceso principal.
Aquí está el ejemplo anterior donde todo el código se ha movido al
count_prefixes()
función. Cuando esa función regresa, se libera toda la memoria. También agregué algunassleep()
llamadas para simular un cálculo de larga duración.Cuando ejecuté esa versión, el uso de la memoria pasó de 6 MB a 4 KB, porque la función liberó toda su memoria cuando terminó.
Ahora aquí hay una versión inspirada en otra respuesta que inicia un segundo hilo para monitorear el uso de la memoria.
El
resource
módulo le permite verificar el uso actual de la memoria y guardar la instantánea del uso máximo de la memoria. La cola permite que el subproceso principal le indique al subproceso del monitor de memoria cuándo imprimir su informe y apagarlo. Cuando se ejecuta, muestra la memoria utilizada por lalist()
llamada:Si está en Linux, puede encontrar
/proc/self/statm
más útil que elresource
módulo.fuente
long_running()
dentro de lacount_prefixes()
función, los valores máximos de RSS no se imprimirán hasta quelong_running()
regrese. ¿O me equivoco?memory_monitor()
se ejecuta en un hilo separado decount_prefixes()
, por lo que las únicas formas en que una puede afectar a la otra son GIL y la cola de mensajes a la que pasomemory_monitor()
. Sospecho que cuandocount_prefixes()
llamasleep()
, alienta el contexto del hilo para cambiar. Si enlong_running()
realidad no está tardando mucho, entonces el contexto del hilo podría no cambiar hasta que vuelva a presionar lasleep()
llamadacount_prefixes()
. Si eso no tiene sentido, publique una nueva pregunta y enlace desde aquí.Si solo desea ver el uso de memoria de un objeto, ( responda a otra pregunta )
fuente
asizeof
asizeof
puede contribuir a RSS, sí. No estoy seguro de qué más quieres decir con "relacionado con".tracemalloc
la solución por debajo de una magnitud más rápidoDivulgar:
Pero agradable por su simplicidad:
Simplemente inserte
using("Label")
donde desea ver lo que está sucediendo. Por ejemplofuente
usage[2]
estás mirandoru_maxrss
, que es solo la parte del proceso que es residente . Esto no ayudará mucho si el proceso se ha cambiado al disco, incluso parcialmente.resource
es un módulo específico de Unix que no funciona en Windows.ru_maxrss
(es decir,usage[2]
) son kB, no páginas, por lo que no es necesario multiplicar ese número porresource.getpagesize()
.Dado que la respuesta aceptada y también la siguiente respuesta mejor votada tienen, en mi opinión, algunos problemas, me gustaría ofrecer una respuesta más que se base estrechamente en la respuesta de Ihor B. con algunas modificaciones pequeñas pero importantes.
Esta solución le permite ejecutar la creación de perfiles ya sea envolviendo una llamada de función con la
profile
función y llamándola, o decorando su función / método con@profile
decorador.La primera técnica es útil cuando desea perfilar algún código de terceros sin alterar su fuente, mientras que la segunda técnica es un poco "más limpia" y funciona mejor cuando no le importa modificar la fuente de la función / método Quiero perfilar.
También modifiqué la salida para que obtenga RSS, VMS y memoria compartida. No me importan mucho los valores "antes" y "después", sino solo el delta, así que los eliminé (si se compara con la respuesta de Ihor B.).
Código de perfil
Ejemplo de uso, suponiendo que el código anterior se guarda como
profile.py
:Esto debería dar como resultado una salida similar a la siguiente:
Un par de notas finales importantes:
profile(my_function, arg)
para perfilarmy_function(arg)
fuente
A continuación se muestra un decorador de funciones simple que permite rastrear cuánta memoria consumió el proceso antes de la llamada a la función, después de la llamada a la función, y cuál es la diferencia:
Aquí está mi blog que describe todos los detalles. ( enlace archivado )
fuente
process.memory_info().rss
asíprocess.get_memory_info().rss
, al menos en ubuntu y python 3.6. relacionados stackoverflow.com/questions/41012058/psutil-error-on-macostal vez ayude:
< ver más >
fuente
fuente