tutorials real blog python memory-management

real - La memoria total utilizada por el proceso de Python?



python blog (10)

¿Hay alguna manera de que un programa Python determine cuánta memoria está usando actualmente? He visto discusiones sobre el uso de la memoria para un solo objeto, pero lo que necesito es el uso total de la memoria para el proceso, de modo que pueda determinar cuándo es necesario comenzar a descartar los datos en caché.


Debajo está mi decorador de funciones que permite rastrear cuánta memoria consumió este proceso antes de la llamada a la función, cuánta memoria usa después de la llamada a la función y cuánto tiempo se ejecuta la función.

import time import os import psutil def elapsed_since(start): return time.strftime("%H:%M:%S", time.gmtime(time.time() - start)) def get_process_memory(): process = psutil.Process(os.getpid()) return process.get_memory_info().rss def track(func): def wrapper(*args, **kwargs): mem_before = get_process_memory() start = time.time() result = func(*args, **kwargs) elapsed_time = elapsed_since(start) mem_after = get_process_memory() print("{}: memory before: {:,}, after: {:,}, consumed: {:,}; exec time: {}".format( func.__name__, mem_before, mem_after, mem_after - mem_before, elapsed_time)) return result return wrapper

Entonces, cuando tienes alguna función decorada con ella

from utils import track @track def list_create(n): print("inside list create") x = [1] * n return x

Podrás ver esta salida:

inside list create list_create: memory before: 45,928,448, after: 46,211,072, consumed: 282,624; exec time: 00:00:00


En Unix, puede usar la herramienta ps para monitorearlo:

$ ps u -p 1347 | awk ''{sum=sum+$6}; END {print sum/1024}''

donde 1347 es alguna identificación de proceso. Además, el resultado está en MB.


En Windows, puede usar WMI ( página de inicio , cheeseshop ):

def memory(): import os from wmi import WMI w = WMI(''.'') result = w.query("SELECT WorkingSet FROM Win32_PerfRawData_PerfProc_Process WHERE IDProcess=%d" % os.getpid()) return int(result[0].WorkingSet)

En Linux (del libro de cocina Python http://code.activestate.com/recipes/286222/ :

import os _proc_status = ''/proc/%d/status'' % os.getpid() _scale = {''kB'': 1024.0, ''mB'': 1024.0*1024.0, ''KB'': 1024.0, ''MB'': 1024.0*1024.0} def _VmB(VmKey): ''''''Private. '''''' global _proc_status, _scale # get pseudo file /proc/<pid>/status try: t = open(_proc_status) v = t.read() t.close() except: return 0.0 # non-Linux? # get VmKey line e.g. ''VmRSS: 9999 kB/n ...'' i = v.index(VmKey) v = v[i:].split(None, 3) # whitespace if len(v) < 3: return 0.0 # invalid format? # convert Vm value to bytes return float(v[1]) * _scale[v[2]] def memory(since=0.0): ''''''Return memory usage in bytes. '''''' return _VmB(''VmSize:'') - since def resident(since=0.0): ''''''Return resident memory usage in bytes. '''''' return _VmB(''VmRSS:'') - since def stacksize(since=0.0): ''''''Return stack size in bytes. '''''' return _VmB(''VmStk:'') - since


Me gusta, gracias por @bayer. Obtengo una herramienta de recuento de procesos específica, ahora.

# Megabyte. $ ps aux | grep python | awk ''{sum=sum+$6}; END {print sum/1024 " MB"}'' 87.9492 MB # Byte. $ ps aux | grep python | awk ''{sum=sum+$6}; END {print sum " KB"}'' 90064 KB

Adjunte mi lista de procesos.

$ ps aux | grep python root 943 0.0 0.1 53252 9524 ? Ss Aug19 52:01 /usr/bin/python /usr/local/bin/beaver -c /etc/beaver/beaver.conf -l /var/log/beaver.log -P /var/run/beaver.pid root 950 0.6 0.4 299680 34220 ? Sl Aug19 568:52 /usr/bin/python /usr/local/bin/beaver -c /etc/beaver/beaver.conf -l /var/log/beaver.log -P /var/run/beaver.pid root 3803 0.2 0.4 315692 36576 ? S 12:43 0:54 /usr/bin/python /usr/local/bin/beaver -c /etc/beaver/beaver.conf -l /var/log/beaver.log -P /var/run/beaver.pid jonny 23325 0.0 0.1 47460 9076 pts/0 S+ 17:40 0:00 python jonny 24651 0.0 0.0 13076 924 pts/4 S+ 18:06 0:00 grep python

Referencia


Para Unixes (Linux, Mac OS X, Solaris) también puede usar la función getrusage() del resource módulo de biblioteca estándar. El objeto resultante tiene el atributo ru_maxrss , que proporciona el uso máximo de memoria para el proceso de llamada:

>>> resource.getrusage(resource.RUSAGE_SELF).ru_maxrss 2656 # peak memory usage (bytes on OS X, kilobytes on Linux)

Los documentos de Python no son claros en cuanto a qué unidades son exactamente, pero la página man de Mac OS X para getrusage(2) describe las unidades como bytes . La página man de Linux no está clara, pero parece ser equivalente a la información de /proc/self/status , que está en kilobytes .

La función getrusage() también puede recibir resource.RUSAGE_CHILDREN para obtener el uso de procesos secundarios y (en algunos sistemas) resource.RUSAGE_BOTH para el uso total (propio y secundario) del proceso.

resource es un módulo de biblioteca estándar.

Si solo le preocupa Linux, puede verificar el archivo /proc/self/status como se describe en una pregunta similar .


Usando sh y os para entrar en la respuesta de python bayer.

float(sh.awk(sh.ps(''u'',''-p'',os.getpid()),''{sum=sum+$6}; END {print sum/1024}''))

La respuesta está en megabytes.


Uso actual de la memoria del proceso actual en Linux, para python 2 y 3 y pypy:

import os def getCurrentMemoryUsage(): '''''' Memory usage in kB '''''' f = open(''/proc/{}/status''.format(os.getpid())) memusage = int(f.read().split(''VmRSS:'')[1].split(''/n'')[0][:-3].strip()) f.close() return memusage

Lo probé en Linux 4.4 y 4.9, pero cualquier versión de Linux debería funcionar.

Buscando en el programa man proc y buscando la información en el archivo /proc/$PID/status , menciona las versiones mínimas para algunos campos (como Linux 2.6.10 para "VmPTE"), pero el campo "VmRSS" (que uso aquí ) no tiene tal mención. Por lo tanto, supongo que ha estado allí desde una versión anterior.


Here hay una solución útil que funciona para varios sistemas operativos, incluidos Linux, Windows 7 x64:

import os import psutil process = psutil.Process(os.getpid()) print(process.memory_info().rss)

En mi instalación actual de Python 2.7, la última línea debe ser

print(process.get_memory_info()[0])

en su lugar (hubo un cambio en la API).


Heapy (y amigos) pueden ser lo que estás buscando.

Además, los cachés generalmente tienen un límite superior fijo en su tamaño para resolver el tipo de problema del que estás hablando. Por ejemplo, echa un vistazo a este decorador de caché LRU .


han = win32api.OpenProcess(win32con.PROCESS_QUERY_INFORMATION|win32con.PROCESS_VM_READ, 0, os.getpid()) process_memory = int(win32process.GetProcessMemoryInfo(han)[''WorkingSetSize''])