suma - Seguimiento*uso de memoria*máximo por una función de Python
mclibre funciones python (5)
Es posible hacer esto con memory_profiler . La función memory_usage
devuelve una lista de valores, estos representan el uso de la memoria a lo largo del tiempo (por defecto en fragmentos de .1 segundo). Si necesita el máximo, solo tome el máximo de esa lista. Pequeño ejemplo:
from memory_profiler import memory_usage
from time import sleep
def f():
# a function that with growing
# memory consumption
a = [0] * 1000
sleep(.1)
b = a * 100
sleep(.1)
c = b * 100
return a
mem_usage = memory_usage(f)
print(''Memory usage (in chunks of .1 seconds): %s'' % mem_usage)
print(''Maximum memory usage: %s'' % max(mem_usage))
En mi caso (memory_profiler 0.25) si imprime el siguiente resultado:
Memory usage (in chunks of .1 seconds): [45.65625, 45.734375, 46.41015625, 53.734375]
Maximum memory usage: 53.734375
Quiero averiguar cuál es la cantidad máxima de RAM asignada durante la llamada a una función (en Python). Hay otras preguntas sobre SO relacionadas con el seguimiento del uso de RAM:
¿Qué perfil de memoria Python se recomienda?
¿Cómo perfilo el uso de la memoria en Python?
pero parece que le permiten seguir el uso de la memoria en el momento en que se llama al método de heap()
(en el caso de guppy). Sin embargo, lo que quiero rastrear es una función en una biblioteca externa que no puedo modificar, y que crece para usar mucha RAM, pero luego la libera una vez que se completa la ejecución de la función. ¿Hay alguna forma de averiguar cuál era la cantidad total de RAM utilizada durante la llamada a la función?
Esta pregunta me pareció bastante interesante y me dio una razón para mirar a Guppy / Heapy, por eso te agradezco.
Intenté durante aproximadamente 2 horas hacer que Heapy supervisara una llamada / proceso de función sin modificar su fuente sin suerte.
Encontré una manera de lograr su tarea usando el resource
biblioteca incorporado de Python. Tenga en cuenta que la documentación no indica qué RU_MAXRSS
valor RU_MAXRSS
. Otro usuario de SO noted que estaba en kB. Ejecutando Mac OSX 7.3 y observando los recursos de mi sistema subir durante el código de prueba a continuación, creo que los valores devueltos están en Bytes , no en kBytes.
Una vista de 10000 pies sobre cómo utilicé la biblioteca de resource
para monitorear la llamada a la biblioteca fue para iniciar la función en un subproceso independiente (monitorizable) y rastrear los recursos del sistema para ese proceso en el hilo principal. A continuación tengo los dos archivos que necesitaría ejecutar para probarlo.
Monitor de recursos de biblioteca - whatever_you_want.py
import resource
import time
from stoppable_thread import StoppableThread
class MyLibrarySniffingClass(StoppableThread):
def __init__(self, target_lib_call, arg1, arg2):
super(MyLibrarySniffingClass, self).__init__()
self.target_function = target_lib_call
self.arg1 = arg1
self.arg2 = arg2
self.results = None
def startup(self):
# Overload the startup function
print "Calling the Target Library Function..."
def cleanup(self):
# Overload the cleanup function
print "Library Call Complete"
def mainloop(self):
# Start the library Call
self.results = self.target_function(self.arg1, self.arg2)
# Kill the thread when complete
self.stop()
def SomeLongRunningLibraryCall(arg1, arg2):
max_dict_entries = 2500
delay_per_entry = .005
some_large_dictionary = {}
dict_entry_count = 0
while(1):
time.sleep(delay_per_entry)
dict_entry_count += 1
some_large_dictionary[dict_entry_count]=range(10000)
if len(some_large_dictionary) > max_dict_entries:
break
print arg1 + " " + arg2
return "Good Bye World"
if __name__ == "__main__":
# Lib Testing Code
mythread = MyLibrarySniffingClass(SomeLongRunningLibraryCall, "Hello", "World")
mythread.start()
start_mem = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss
delta_mem = 0
max_memory = 0
memory_usage_refresh = .005 # Seconds
while(1):
time.sleep(memory_usage_refresh)
delta_mem = (resource.getrusage(resource.RUSAGE_SELF).ru_maxrss) - start_mem
if delta_mem > max_memory:
max_memory = delta_mem
# Uncomment this line to see the memory usuage during run-time
# print "Memory Usage During Call: %d MB" % (delta_mem / 1000000.0)
# Check to see if the library call is complete
if mythread.isShutdown():
print mythread.results
break;
print "/nMAX Memory Usage in MB: " + str(round(max_memory / 1000.0, 3))
Hilo stoppable_thread.py - stoppable_thread.py
import threading
import time
class StoppableThread(threading.Thread):
def __init__(self):
super(StoppableThread, self).__init__()
self.daemon = True
self.__monitor = threading.Event()
self.__monitor.set()
self.__has_shutdown = False
def run(self):
''''''Overloads the threading.Thread.run''''''
# Call the User''s Startup functions
self.startup()
# Loop until the thread is stopped
while self.isRunning():
self.mainloop()
# Clean up
self.cleanup()
# Flag to the outside world that the thread has exited
# AND that the cleanup is complete
self.__has_shutdown = True
def stop(self):
self.__monitor.clear()
def isRunning(self):
return self.__monitor.isSet()
def isShutdown(self):
return self.__has_shutdown
###############################
### User Defined Functions ####
###############################
def mainloop(self):
''''''
Expected to be overwritten in a subclass!!
Note that Stoppable while(1) is handled in the built in "run".
''''''
pass
def startup(self):
''''''Expected to be overwritten in a subclass!!''''''
pass
def cleanup(self):
''''''Expected to be overwritten in a subclass!!''''''
pass
Esto parece funcionar en Windows. No sé sobre otros sistemas operativos.
In [50]: import os
In [51]: import psutil
In [52]: process = psutil.Process(os.getpid())
In [53]: process.get_ext_memory_info().peak_wset
Out[53]: 41934848
He estado luchando con esta tarea también. Después de experimentar con psutil y métodos de Adam, escribí una función (créditos a Adam Lewis) para medir la memoria utilizada por una función específica. Las personas pueden encontrar más fácil de agarrar y usar.
2) prueba measure_memory_usage
Descubrí que los materiales sobre el uso de subprocesos y la superclase primordial son realmente útiles para comprender lo que Adam está haciendo en sus guiones. Lo siento, no puedo publicar los enlaces debido a mi limitación máxima de "2 enlaces".
Puede usar el recurso de la biblioteca de Python para obtener el uso de la memoria.
import resource
resource.getrusage(resource.RUSAGE_SELF).ru_maxrss
Dará uso de memoria en kilobytes, para convertir en MB divide por 1000.