for - Tamaño en memoria de una estructura de Python
for en python 3 (6)
Cuando utiliza la función incorporada dir ([objeto]), puede usar el tamaño de la función incorporada.
>>> a = -1
>>> a.__sizeof__()
24
¿Hay alguna referencia para el tamaño de la memoria de la estructura de datos de Python en plataformas de 32 y 64 bits?
Si no, sería bueno tenerlo en SO. ¡Cuanto más exhaustivo, mejor! Entonces, ¿cuántos bytes utilizan las siguientes estructuras de Python (dependiendo de la len
y el tipo de contenido cuando sea relevante)?
-
int
-
float
- referencia
-
str
- cadena unicode
-
tuple
-
list
-
dict
-
set
-
array.array
-
numpy.array
-
deque
- objeto de clases de nuevo estilo
- objeto de clases de estilo antiguo
- ... y todo lo que estoy olvidando!
(Para contenedores que solo conservan referencias a otros objetos, obviamente no queremos contar el tamaño del artículo, ya que podría compartirse).
Además, ¿hay alguna manera de obtener la memoria utilizada por un objeto en tiempo de ejecución (recursiva o no)?
He estado felizmente usando el pympler para tales tareas. Es compatible con muchas versiones de Python: ¡el módulo asizeof
, en particular, vuelve a 2.2!
Por ejemplo, usando el ejemplo from pympler import asizeof
pero con from pympler import asizeof
al inicio e print asizeof.asizeof(v)
al final, veo (sistema Python 2.5 en MacOSX 10.5):
$ python pymp.py
set 120
unicode 32
tuple 32
int 16
decimal 152
float 16
list 40
object 0
dict 144
str 32
Claramente hay una aproximación aquí, pero la he encontrado muy útil para el análisis y ajuste de huella.
La recomendación de una pregunta anterior sobre esto era usar sys.getsizeof() , citando:
>>> import sys
>>> x = 2
>>> sys.getsizeof(x)
14
>>> sys.getsizeof(sys.getsizeof)
32
>>> sys.getsizeof(''this'')
38
>>> sys.getsizeof(''this also'')
48
Podrías tomar este enfoque:
>>> import sys
>>> import decimal
>>>
>>> d = {
... "int": 0,
... "float": 0.0,
... "dict": dict(),
... "set": set(),
... "tuple": tuple(),
... "list": list(),
... "str": "a",
... "unicode": u"a",
... "decimal": decimal.Decimal(0),
... "object": object(),
... }
>>> for k, v in sorted(d.iteritems()):
... print k, sys.getsizeof(v)
...
decimal 40
dict 140
float 16
int 12
list 36
object 8
set 116
str 25
tuple 28
unicode 28
30/09/2012
python 2.7 (Linux, 32 bits):
decimal 36
dict 136
float 16
int 12
list 32
object 8
set 112
str 22
tuple 24
unicode 32
Python 3.3 (Linux, 32 bits)
decimal 52
dict 144
float 16
int 14
list 32
object 8
set 112
str 26
tuple 24
unicode 26
2016-08-01
OSX, Python 2.7.10 (predeterminado, 23 de octubre de 2015, 19:19:21) [GCC 4.2.1 Apple LLVM 7.0.0 compatible (clang-700.0.59.5)] en darwin
decimal 80
dict 280
float 24
int 24
list 72
object 16
set 232
str 38
tuple 56
unicode 52
Pruebe el generador de perfiles de memoria. memoria perfiladora
Line # Mem usage Increment Line Contents
==============================================
3 @profile
4 5.97 MB 0.00 MB def my_func():
5 13.61 MB 7.64 MB a = [1] * (10 ** 6)
6 166.20 MB 152.59 MB b = [2] * (2 * 10 ** 7)
7 13.61 MB -152.59 MB del b
8 13.61 MB 0.00 MB return a
También puedes usar el módulo guppy .
>>> from guppy import hpy; hp=hpy()
>>> hp.heap()
Partition of a set of 25853 objects. Total size = 3320992 bytes.
Index Count % Size % Cumulative % Kind (class / dict of class)
0 11731 45 929072 28 929072 28 str
1 5832 23 469760 14 1398832 42 tuple
2 324 1 277728 8 1676560 50 dict (no owner)
3 70 0 216976 7 1893536 57 dict of module
4 199 1 210856 6 2104392 63 dict of type
5 1627 6 208256 6 2312648 70 types.CodeType
6 1592 6 191040 6 2503688 75 function
7 199 1 177008 5 2680696 81 type
8 124 0 135328 4 2816024 85 dict of class
9 1045 4 83600 3 2899624 87 __builtin__.wrapper_descriptor
<90 more rows. Type e.g. ''_.more'' to view.>
Y:
>>> hp.iso(1, [1], "1", (1,), {1:1}, None)
Partition of a set of 6 objects. Total size = 560 bytes.
Index Count % Size % Cumulative % Kind (class / dict of class)
0 1 17 280 50 280 50 dict (no owner)
1 1 17 136 24 416 74 list
2 1 17 64 11 480 86 tuple
3 1 17 40 7 520 93 str
4 1 17 24 4 544 97 int
5 1 17 16 3 560 100 types.NoneType
Todas estas respuestas recogen información de tamaño superficial. Sospecho que los visitantes de esta pregunta terminarán aquí buscando responder la pregunta: "¿Qué tan grande es este objeto complejo en la memoria?"
Hay una gran respuesta aquí: https://goshippo.com/blog/measure-real-size-any-python-object/
La frase final:
import sys
def get_size(obj, seen=None):
"""Recursively finds size of objects"""
size = sys.getsizeof(obj)
if seen is None:
seen = set()
obj_id = id(obj)
if obj_id in seen:
return 0
# Important mark as seen *before* entering recursion to gracefully handle
# self-referential objects
seen.add(obj_id)
if isinstance(obj, dict):
size += sum([get_size(v, seen) for v in obj.values()])
size += sum([get_size(k, seen) for k in obj.keys()])
elif hasattr(obj, ''__dict__''):
size += get_size(obj.__dict__, seen)
elif hasattr(obj, ''__iter__'') and not isinstance(obj, (str, bytes, bytearray)):
size += sum([get_size(i, seen) for i in obj])
return size
Usado así:
In [1]: get_size(1)
Out[1]: 24
In [2]: get_size([1])
Out[2]: 104
In [3]: get_size([[1]])
Out[3]: 184
Si desea conocer más profundamente el modelo de memoria de Python, hay un excelente artículo aquí que tiene un fragmento de código de "tamaño total" similar como parte de una explicación más larga: https://code.tutsplus.com/tutorials/understand-how-much-memory-your-python-objects-use--cms-25609