punteros objetos objeto memoria manejo maneja limpiar liberar eliminar destruir como python memory profiling

objetos - manejo de memoria en python



¿Cómo perfilo el uso de la memoria en Python? (6)

Recientemente me interesaron 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 timeit magic en IPython es suficiente), pero también me interesa el uso de la memoria para poder explorar esos intercambios también ( por ejemplo, el costo de almacenar en caché una tabla de valores previamente calculados versus volver a calcularlos según sea necesario). ¿Hay algún módulo que describa el uso de memoria de una función determinada para mí?


A continuación se muestra un decorador de funciones simple que permite rastrear la cantidad de memoria consumida antes de la llamada a la función, después de la llamada a la función, y cuál es la diferencia:

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 profile(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

Aquí está mi blog que describe todos los detalles.


Este ya ha sido respondido aquí: Python memory profiler

Básicamente, haces algo así (citado de Guppy-PE ):

>>> from guppy import hpy; h=hpy() >>> h.heap() Partition of a set of 48477 objects. Total size = 3265516 bytes. Index Count % Size % Cumulative % Kind (class / dict of class) 0 25773 53 1612820 49 1612820 49 str 1 11699 24 483960 15 2096780 64 tuple 2 174 0 241584 7 2338364 72 dict of module 3 3478 7 222592 7 2560956 78 types.CodeType 4 3296 7 184576 6 2745532 84 function 5 401 1 175112 5 2920644 89 dict of class 6 108 0 81888 3 3002532 92 dict (no owner) 7 114 0 79632 2 3082164 94 dict of type 8 117 0 51336 2 3133500 96 type 9 667 1 24012 1 3157512 97 __builtin__.wrapper_descriptor <76 more rows. Type e.g. ''_.more'' to view.> >>> h.iso(1,[],{}) Partition of a set of 3 objects. Total size = 176 bytes. Index Count % Size % Cumulative % Kind (class / dict of class) 0 1 33 136 77 136 77 dict (no owner) 1 1 33 28 16 164 93 list 2 1 33 12 7 176 100 int >>> x=[] >>> h.iso(x).sp 0: h.Root.i0_modules[''__main__''].__dict__[''x''] >>>


Para un enfoque realmente simple, intente:

import resource def using(point=""): usage=resource.getrusage(resource.RUSAGE_SELF) return ''''''%s: usertime=%s systime=%s mem=%s mb ''''''%(point,usage[0],usage[1], (usage[2]*resource.getpagesize())/1000000.0 )

Simplemente inserte using("Label") donde desea ver lo que está pasando.


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.

from collections import Counter import linecache import os import tracemalloc def display_top(snapshot, key_type=''lineno'', limit=3): snapshot = snapshot.filter_traces(( tracemalloc.Filter(False, "<frozen importlib._bootstrap>"), tracemalloc.Filter(False, "<unknown>"), )) top_stats = snapshot.statistics(key_type) print("Top %s lines" % limit) for index, stat in enumerate(top_stats[:limit], 1): frame = stat.traceback[0] # replace "/path/to/module/file.py" with "module/file.py" filename = os.sep.join(frame.filename.split(os.sep)[-2:]) print("#%s: %s:%s: %.1f KiB" % (index, filename, frame.lineno, stat.size / 1024)) line = linecache.getline(frame.filename, frame.lineno).strip() if line: print('' %s'' % line) other = top_stats[limit:] if other: size = sum(stat.size for stat in other) print("%s other: %.1f KiB" % (len(other), size / 1024)) total = sum(stat.size for stat in top_stats) print("Total allocated size: %.1f KiB" % (total / 1024)) tracemalloc.start() counts = Counter() fname = ''/usr/share/dict/american-english'' with open(fname) as words: words = list(words) for word in words: prefix = word[:3] counts[prefix] += 1 print(''Top prefixes:'', counts.most_common(3)) snapshot = tracemalloc.take_snapshot() display_top(snapshot)

Y aquí están los resultados:

Top prefixes: [(''con'', 1220), (''dis'', 1002), (''pro'', 809)] Top 3 lines #1: scratches/memory_test.py:37: 6527.1 KiB words = list(words) #2: scratches/memory_test.py:39: 247.7 KiB prefix = word[:3] #3: scratches/memory_test.py:40: 193.0 KiB counts[prefix] += 1 4 other: 4.3 KiB Total allocated size: 6972.1 KiB


Yo solo quiero ver el uso de memoria de un objeto ( respuesta a otra pregunta )

Hay un módulo llamado Pympler que contiene el módulo asizeof .

Use de la siguiente manera:

from pympler import asizeof asizeof.asizeof(my_object)

A diferencia de sys.getsizeof , funciona para tus objetos creados por sys.getsizeof mismo.

>>> asizeof.asizeof(tuple(''bcd'')) 200 >>> asizeof.asizeof({''foo'': ''bar'', ''baz'': ''bar''}) 400 >>> asizeof.asizeof({}) 280 >>> asizeof.asizeof({''foo'':''bar''}) 360 >>> asizeof.asizeof(''foo'') 40 >>> asizeof.asizeof(Bar()) 352 >>> asizeof.asizeof(Bar().__dict__) 280

>>> help(asizeof.asizeof) Help on function asizeof in module pympler.asizeof: asizeof(*objs, **opts) Return the combined size in bytes of all objects passed as positional arguments.


tal vez ayuda:
< ver más >

pip install gprof2dot sudo apt-get install graphviz gprof2dot -f pstats profile_for_func1_001 | dot -Tpng -o profile.png def profileit(name): """ @profileit("profile_for_func1_001") """ def inner(func): def wrapper(*args, **kwargs): prof = cProfile.Profile() retval = prof.runcall(func, *args, **kwargs) # Note use of name from outer scope prof.dump_stats(name) return retval return wrapper return inner @profileit("profile_for_func1_001") def func1(...)