Kích thước trong bộ nhớ của cấu trúc Python


118

Có tham chiếu cho kích thước bộ nhớ của cấu trúc dữ liệu Python trên nền tảng 32 và 64 bit không?

Nếu không, điều này sẽ rất tuyệt nếu có nó trên SO. Càng đầy đủ càng tốt! Vậy có bao nhiêu byte được sử dụng bởi các cấu trúc Python sau đây (tùy thuộc vào lenvà loại nội dung khi có liên quan)?

  • int
  • float
  • tài liệu tham khảo
  • str
  • chuỗi unicode
  • tuple
  • list
  • dict
  • set
  • array.array
  • numpy.array
  • deque
  • đối tượng lớp kiểu mới
  • đối tượng lớp kiểu cũ
  • ... và mọi thứ tôi đang quên!

(Đối với các vùng chứa chỉ giữ các tham chiếu đến các đối tượng khác, chúng tôi rõ ràng không muốn tính kích thước của chính mục đó, vì nó có thể được chia sẻ.)

Hơn nữa, có cách nào để lấy bộ nhớ được một đối tượng sử dụng trong thời gian chạy (đệ quy hay không)?


Bạn có thể tìm thấy nhiều giải thích hữu ích tại đây stackoverflow.com/questions/1059674/python-memory-model . Tôi muốn nhìn thấy một cái nhìn tổng quan hệ thống hơn, mặc dù
LeMiz

3
Đối với một mảng NumPy a, hãy sử dụng a.nbytes.
Will

Nếu bạn quan tâm đến chế độ xem đồ họa của cái này, tôi đã vẽ sơ đồ về nó một lần: stackoverflow.com/a/30008338/2087463
tmthydvnprt

Câu trả lời:


145

Đề xuất từ một câu hỏi trước đó về vấn đề này là sử dụng sys.getsizeof () , trích dẫn:

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

Bạn có thể thực hiện cách tiếp cận này:

>>> 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 (mặc định, ngày 23 tháng 10 năm 2015, 19:19:21) [GCC 4.2.1 Tương thích Apple LLVM 7.0.0 (clang-700.0.59.5)] trên darwin

decimal 80
dict 280
float 24
int 24
list 72
object 16
set 232
str 38
tuple 56
unicode 52

1
Cảm ơn, và xin lỗi vì sự dupe cho câu hỏi thứ hai ... quá xấu Tôi đang sử dụng 2.5 và không 2,6 ...
LeMiz

Tôi quên rằng tôi có một hộp ảo với ubuntu gần đây trên đó! Đó là kỳ lạ, sys.getsizeof (dict) là 136 đối với tôi (python 2,6 chạy trên một kubuntu vm, được tổ chức bởi OS X, vì vậy tôi không chắc chắn về bất cứ điều gì)
LeMiz

@LeMiz: Đối với tôi (Python 2.6, Windows XP SP3), sys.getsizeof (dict) -> 436; sys.getsizeof (dict ()) -> 140
John Machin

LeMiz-Kubuntu: python2.6 Python 2.6.2 (release26-Maint, ngày 19 tháng 4 năm 2009, 01:56:41) [GCC 4.3.3] trên linux2 Loại "trợ giúp", "bản quyền", "tín dụng" hoặc "giấy phép" để biết thêm thông tin. >>> import sys >>> sys.getsizeof (dict) 436 >>> sys.getsizeof (dict ()) 136
LeMiz

1
không nên các giá trị được 0, 0.0, ''u''nhất quán?
SilentGhost

37

Tôi đã rất vui khi sử dụng pympler cho các nhiệm vụ như vậy. Nó tương thích với nhiều phiên bản Python - asizeofđặc biệt là mô-đun quay trở lại 2.2!

Ví dụ: sử dụng ví dụ của hughdbrown nhưng với from pympler import asizeofở đầu và print asizeof.asizeof(v)cuối, tôi thấy (hệ thống Python 2.5 trên 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

Rõ ràng là có một số ước lượng ở đây, nhưng tôi thấy nó rất hữu ích cho việc phân tích và điều chỉnh dấu chân.


1
Một số điều tò mò: hầu hết các bạn có số cao hơn 4; đối tượng là 0; và số thập phân lớn hơn khoảng 4 lần theo ước tính của bạn.
hughdbrown

1
Vâng. "4 cao hơn" thực sự hầu hết trông giống như "làm tròn đến bội số của 8" mà tôi tin là đúng với cách malloc cư xử ở đây. Không hiểu tại sao số thập phân lại bị bóp méo như vậy (với pympler trên 2.6 cũng vậy).
Alex Martelli

2
Trên thực tế, bạn nên sử dụng pympler.asizeof.flatsize () để có một chức năng tương tự như sys.getsizeof (). Ngoài ra còn có một tham số align = bạn có thể sử dụng (mặc định là 8 như Alex đã chỉ ra).
Pankrat 11/09/09

@AlexMartelli Xin chào Alex! .. Tại sao kích thước tối thiểu của một char trong python là 25 byte. >>> getsizeof('a')cho 25>>> getsizeof('ab')đưa ra 26'
Grijesh Chauhan

1
Tôi giả sử kích thước tính bằng byte, nhưng tại sao nó không viết bất cứ nơi nào, ngay cả trong pythonhosted.org/Pympler
Zhomart

35

Những câu trả lời này đều thu thập thông tin về kích thước nông. Tôi nghi ngờ rằng những người truy cập câu hỏi này sẽ kết thúc ở đây để trả lời câu hỏi, "Vật thể phức tạp này lớn đến mức nào trong bộ nhớ?"

Có một câu trả lời tuyệt vời ở đây: https://goshippo.com/blog/measure-real-size-any-python-object/

Đường đột:

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

Được sử dụng như vậy:

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

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

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

Nếu bạn muốn biết sâu hơn về mô hình bộ nhớ của Python, có một bài viết tuyệt vời ở đây có đoạn mã "tổng kích thước" tương tự như một phần của lời giải thích dài hơn: https://code.tutsplus.com/tutorials/und hieu-how- much-memory-your-python-objects-use - cms-25609


Vì vậy, điều này sẽ mang lại tổng dung lượng bộ nhớ được sử dụng, ví dụ, một mệnh lệnh chứa nhiều mảng và / hoặc các mảng khác?
Charly Empereur-mot

1
@ CharlyEmpereur-mot yep.
Kobold

Câu trả lời chính xác. Tuy nhiên, nó dường như không hoạt động đối với các đối tượng cython đã biên dịch. Trong trường hợp của tôi, phương thức này trả về 96cho một con trỏ tới một đối tượng cython trong bộ nhớ
ferdynator

8

Hãy thử trình biên dịch bộ nhớ. hồ sơ bộ nhớ

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

1
Độ chính xác dường như là 1 / 100MB hoặc 10,24 byte. Điều này là tốt cho phân tích vĩ mô, nhưng tôi nghi ngờ rằng độ chính xác như vậy sẽ dẫn đến việc so sánh chính xác các cấu trúc dữ liệu như đã hỏi trong câu hỏi.
Zoran Pavlovic

7

Ngoài ra, bạn có thể sử dụng mô-đun 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.>

Và:

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

0

Người ta cũng có thể sử dụng tracemallocmô-đun từ thư viện chuẩn Python. Nó dường như hoạt động tốt đối với các đối tượng có lớp được triển khai trong C (không giống như Pympler, chẳng hạn).


-1

Khi bạn sử dụng dir([object])chức năng tích hợp, bạn có thể nhận được __sizeof__chức năng tích hợp sẵn.

>>> a = -1
>>> a.__sizeof__()
24
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.