2009-05-22 10 views

Respuesta

31

Una solución simple para Linux y otros sistemas con /proc/self/status es el siguiente código, que yo uso en un proyecto mío:

def memory_usage(): 
    """Memory usage of the current process in kilobytes.""" 
    status = None 
    result = {'peak': 0, 'rss': 0} 
    try: 
     # This will only work on systems with a /proc file system 
     # (like Linux). 
     status = open('/proc/self/status') 
     for line in status: 
      parts = line.split() 
      key = parts[0][2:-1].lower() 
      if key in result: 
       result[key] = int(parts[1]) 
    finally: 
     if status is not None: 
      status.close() 
    return result 

Devuelve el tamaño de la memoria residente actual y el pico (que es probablemente lo que las personas quieren decir cuando hablan sobre la cantidad de RAM que usa una aplicación). Es fácil extenderlo para tomar otras piezas de información del archivo /proc/self/status.

Para los curiosos: la salida completa de cat /proc/self/status se parece a esto:

% cat /proc/self/status 
Name: cat 
State: R (running) 
Tgid: 4145 
Pid: 4145 
PPid: 4103 
TracerPid:  0 
Uid: 1000 1000 1000 1000 
Gid: 1000 1000 1000 1000 
FDSize: 32 
Groups: 20 24 25 29 40 44 46 100 1000 
VmPeak:  3580 kB 
VmSize:  3580 kB 
VmLck:   0 kB 
VmHWM:  472 kB 
VmRSS:  472 kB 
VmData:  160 kB 
VmStk:  84 kB 
VmExe:  44 kB 
VmLib:  1496 kB 
VmPTE:  16 kB 
Threads:  1 
SigQ: 0/16382 
SigPnd: 0000000000000000 
ShdPnd: 0000000000000000 
SigBlk: 0000000000000000 
SigIgn: 0000000000000000 
SigCgt: 0000000000000000 
CapInh: 0000000000000000 
CapPrm: 0000000000000000 
CapEff: 0000000000000000 
CapBnd: ffffffffffffffff 
Cpus_allowed: 03 
Cpus_allowed_list:  0-1 
Mems_allowed: 1 
Mems_allowed_list:  0 
voluntary_ctxt_switches:  0 
nonvoluntary_ctxt_switches:  0 
+2

es el pico/residente en kb o bytes? – Shabbyrobe

+1

Buena pregunta: está en kilobytes, he agregado esa información a la respuesta original. –

+0

Gracias a todos por la gran respuesta. Como un aparte, ¿tendría alguna idea de por qué el pico termina por encima de 80 mb (!!!) si engendro un montón de hilos, a pesar de que el residente se mantiene relativamente bajo? Además, ¿tiene alguna pista sobre cómo hacer esto en Win32? – Shabbyrobe

17

También es posible usar la función getrusage() desde el módulo de la biblioteca estándar resource. El objeto resultante tiene el atributo ru_maxrss, lo que da uso total de memoria para el proceso de llamada:

>>> import resource 
>>> resource.getrusage(resource.RUSAGE_SELF).ru_maxrss 
2656 

la Python docs no son claras en lo que las unidades son exactamente, pero el Mac OS X man page para getrusage(2) describe las unidades como kilobytes.

La página man de Linux no está clara, pero parece ser equivalente a la información /proc/self/status (es decir, kilobytes) que se describe en la respuesta aceptada. Por el mismo proceso que el anterior, que se ejecuta en Linux, la función que aparece en la respuesta aceptada da:

>>> memory_usage()          
{'peak': 6392, 'rss': 2656} 

esto puede no ser tan fácil de usar como la solución /proc/self/status, pero es la biblioteca estándar, por lo que (siempre las unidades son estándar) debe ser multiplataforma y utilizable en sistemas que no tienen /proc/ (por ejemplo, Mac OS X y otros Unixes, tal vez Windows).

También, getrusage() función puede también darse resource.RUSAGE_CHILDREN para obtener el uso de procesos secundarios, y (en algunos sistemas) resource.RUSAGE_BOTH para el total de (auto y el niño) el uso de proceso.

Esto cubrirá el caso memory_get_usage(), pero no incluye el uso máximo. No estoy seguro si otras funciones del módulo resource pueden dar un uso máximo.

+0

Mi OSX (lion) da: '35819520' en un proceso que estoy ejecutando y estoy bastante seguro de que es' 35MB' en vez de '35GB', por lo que parecen ser bytes. :) –

+2

En mi máquina Ubuntu 11.10, obtengo resource.getrusage() como un valor que está mucho más cerca del valor máximo de memory_usage() que del rss. ¿Estás seguro de que ru_maxrss se refiere al uso actual de la memoria y no al uso máximo de la memoria? – Phani

+1

@Phani Parece que también es un uso máximo para mí. Obtenga más información acerca de ru_maxrss en esta respuesta: http://stackoverflow.com/a/12050966/67184 –

10

Reglas de respuesta aceptadas, pero podría ser más fácil (y más portátil) usar psutil. Hace lo mismo y mucho más.

ACTUALIZACIÓN: muppy también es muy conveniente (y mucho mejor documentado que guppy/heapy).

+0

La tuya es mi respuesta aceptada, pero yo no fui quien hizo la pregunta, así que lo mejor que puedo darte es un voto alternativo. – CashCow

+0

¡Gracias! He encontrado que [muppy] (http://packages.python.org/Pympler/muppy.html) es aún mejor en algunos aspectos, y también está muy bien documentado: vale la pena verificar si tiene problemas de pérdida de memoria. – johndodo

+0

Para detalles, vea la (casi la misma) respuesta: http://stackoverflow.com/a/21632554/1959808 –

0

/proc/self/status tiene las siguientes claves relevantes:

  • VmPeak: Pico tamaño de la memoria virtual.
  • VmSize: Tamaño de la memoria virtual.
  • VmHWM: Tamaño de residente de pico ("marca de nivel de agua alto").
  • VmRSS: Tamaño del conjunto de residentes.

lo tanto, si la preocupación es residente en memoria, el siguiente código me puede utilizarse para recuperarlo:

def get_proc_status(keys = None): 
    with open('/proc/self/status') as f: 
     data = dict(map(str.strip, line.split(':', 1)) for line in f) 

    return tuple(data[k] for k in keys) if keys else data 

peak, current = get_proc_status(('VmHWM', 'VmRSS')) 
print(peak, current) # outputs: 14280 kB 13696 kB 

He aquí un article by memory_profiler's author que explica que getrusage 's ru_maxrss no siempre es una medida práctica. También tenga en cuenta que, VmHWM puede diferir de ru_maxrss (lo que veo en algunos casos ru_maxrss es mayor). Pero en el caso sencillo que son los mismos:

import resource 


def report(): 
    maxrss = resource.getrusage(resource.RUSAGE_SELF).ru_maxrss 
    peak, current = get_proc_status(('VmHWM', 'VmRSS')) 
    print(current, peak, maxrss) 


report() 

s = ' ' * 2 ** 28 # 256MiB 
report() 

s = None 
report() 

Además aquí es una muy comprensible e informativa case study by atop authors que explica lo que es el kernel, la memoria virtual y residente, y la forma en que son interdependientes.