Wielkość w pamięci struktury Pythona

Czy istnieje odniesienie do wielkości pamięci struktury danych Pythona na platformach 32-i 64-bitowych?

Jeśli nie, to byłoby miło mieć go na tak. Im bardziej wyczerpujący tym lepiej! Więc ile bajtów jest używanych przez następujące struktury Pythona (w zależności od len i typu zawartości, gdy jest to istotne)?

  • int
  • float
  • odniesienie
  • str
  • unicode string
  • tuple
  • list
  • dict
  • set
  • array.array
  • numpy.array
  • deque
  • obiekt klas nowego stylu
  • obiekt klas starego stylu
  • ... i wszystko, o czym zapominam!

(W przypadku kontenerów, które przechowują tylko odniesienia do innych obiektów, oczywiście nie chcemy liczyć rozmiaru samego elementu, ponieważ może on być współdzielony.)

Ponadto, czy istnieje sposób, aby pamięć używana przez obiekt w czasie wykonywania (rekurencyjnie czy nie)?

Author: Michael Currie, 2009-08-26

6 answers

Rekomendacją z wcześniejszego pytania było użycie sys.getsizeof () , cytując:

>>> import sys
>>> x = 2
>>> sys.getsizeof(x)
14
>>> sys.getsizeof(sys.getsizeof)
32
>>> sys.getsizeof('this')
38
>>> sys.getsizeof('this also')
48

Można przyjąć takie podejście:

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

2012-09-30

Python 2.7 (linux, 32-bit):

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-bit)

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 (default, Oct 23 2015, 19:19:21) [GCC 4.2.1 Compatible Apple LLVM 7.0.0( clang-700.0.59.5)] on darwin

decimal 80
dict 280
float 24
int 24
list 72
object 16
set 232
str 38
tuple 56
unicode 52
 118
Author: hughdbrown,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:34:39

Do takich zadań chętnie używałem pymplera. Jest kompatybilny z wieloma wersjami Pythona - moduł asizeof w szczególności sięga 2.2!

Na przykład, używając przykładu hughdbrown, ale z from pympler import asizeof na początku i print asizeof.asizeof(v) na końcu, widzę (system Python 2.5 na 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

Najwyraźniej jest tu jakieś przybliżenie, ale uznałem to za bardzo przydatne do analizy i strojenia footprint.

 32
Author: Alex Martelli,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-08-26 01:45:10

Wszystkie te odpowiedzi zbierają informacje o niewielkich rozmiarach. Podejrzewam, że odwiedzający to pytanie będą tutaj szukać odpowiedzi na pytanie: "jak duży jest ten złożony obiekt w pamięci?"

Tu jest świetna odpowiedź: https://goshippo.com/blog/measure-real-size-any-python-object/

Puenta:

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

Używane tak:

In [1]: get_size(1)
Out[1]: 24

In [2]: get_size([1])
Out[2]: 104

In [3]: get_size([[1]])
Out[3]: 184

Jeśli chcesz poznać model pamięci Pythona głębiej, jest tu świetny artykuł, który ma podobny " Całkowity rozmiar" fragment kodu jako część dłuższego wyjaśnienia: https://code.tutsplus.com/tutorials/understand-how-much-memory-your-python-objects-use--cms-25609

 18
Author: Kobold,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-30 05:26:14

Spróbuj memory profiler. memory profiler

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
 7
Author: Tampa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-01 03:56:49

Możesz również użyć modułu 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.>

I:

>>> 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
 7
Author: Omid Raha,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-26 11:04:28

Kiedy używasz wbudowanej funkcji dir([object]), możesz użyć wbudowanej funkcji sizeof .

>>> a = -1
>>> a.__sizeof__()
24
 0
Author: hello_god,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-05 02:48:49