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 porsys.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(...)