Làm cách nào để xác định kích thước của một đối tượng trong Python?


682

Tôi muốn biết làm thế nào để có được kích thước của các đối tượng như một chuỗi, số nguyên, v.v. trong Python.

Câu hỏi liên quan: Có bao nhiêu byte cho mỗi phần tử trong danh sách Python (tuple)?

Tôi đang sử dụng tệp XML chứa các trường kích thước chỉ định kích thước của giá trị. Tôi phải phân tích cú pháp XML này và thực hiện mã hóa. Khi tôi muốn thay đổi giá trị của một trường cụ thể, tôi sẽ kiểm tra trường kích thước của giá trị đó. Ở đây tôi muốn so sánh xem giá trị mới mà tôi phải nhập có cùng kích thước như trong XML hay không. Tôi cần kiểm tra kích thước của giá trị mới. Trong trường hợp của một chuỗi tôi có thể nói chiều dài của nó. Nhưng trong trường hợp int, float, v.v ... tôi bối rối.

Câu trả lời:


665

Chỉ cần sử dụng hàm sys.getsizeof được xác định trong sysmô-đun.

sys.getsizeof(object[, default]):

Trả về kích thước của một đối tượng tính bằng byte. Đối tượng có thể là bất kỳ loại đối tượng. Tất cả các đối tượng tích hợp sẽ trả về kết quả chính xác, nhưng điều này không phải đúng với các tiện ích mở rộng của bên thứ ba vì nó là triển khai cụ thể.

Đối defaultsố cho phép xác định một giá trị sẽ được trả về nếu loại đối tượng không cung cấp phương tiện để lấy kích thước và sẽ gây ra a TypeError.

getsizeofgọi __sizeof__phương thức của đối tượng và thêm một bộ thu gom rác bổ sung nếu đối tượng được quản lý bởi bộ thu gom rác.

Ví dụ sử dụng, trong python 3.0:

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

Nếu bạn ở python <2.6 và không có, sys.getsizeofbạn có thể sử dụng mô-đun mở rộng này để thay thế. Không bao giờ sử dụng nó mặc dù.


181
Vui lòng thêm vào từ chối trách nhiệm rằng nó sẽ không đúng với các đối tượng lồng nhau hoặc các ký tự hoặc ký tự lồng nhau trong danh sách, v.v.
JohnnyM

8
@ChaimG đó là vì mọi đối tượng chỉ sử dụng 32 byte !! Phần còn lại là các tham chiếu đến các đối tượng khác. Nếu bạn muốn tính đến các đối tượng được tham chiếu, bạn phải xác định __sizeof__phương thức cho lớp của mình. Lớp dictpython tích hợp sẵn định nghĩa nó, đó là lý do tại sao bạn nhận được kết quả chính xác khi sử dụng đối tượng kiểu dict.
nosklo

19
Tuyên bố từ chối trách nhiệm và các trường hợp ngoại lệ đối với công việc này bao gồm hầu hết các trường hợp sử dụng làm cho getsizeofchức năng của giá trị nhỏ ra khỏi hộp.
Robino

7
Tại sao số nguyên 2 được lưu trữ trong 24 byte?
Saher Ahwal 19/03/18

4
@SaherAhwal nó không chỉ là một số nguyên, mà là một đối tượng đầy đủ với các phương thức, thuộc tính, địa chỉ ...
nosklo

369

Làm cách nào để xác định kích thước của một đối tượng trong Python?

Câu trả lời, "Chỉ cần sử dụng sys.getsizeof" không phải là một câu trả lời hoàn chỉnh.

Câu trả lời đó không hoạt động trực tiếp cho các đối tượng dựng sẵn, nhưng nó không tính đến những gì các đối tượng đó có thể chứa, cụ thể, loại nào, chẳng hạn như các đối tượng tùy chỉnh, bộ dữ liệu, danh sách, dicts và bộ chứa. Chúng có thể chứa các thể hiện lẫn nhau, cũng như số, chuỗi và các đối tượng khác.

Một câu trả lời đầy đủ hơn

Sử dụng 64 bit Python 3.6 từ bản phân phối Anaconda, với sys.getsizeof, tôi đã xác định kích thước tối thiểu của các đối tượng sau và lưu ý rằng các tập hợp và dicts không gian preallocate để những cái trống không tăng trở lại cho đến sau một lượng đã đặt (có thể thay đổi theo cách thực hiện ngôn ngữ):

Con trăn 3:

Empty
Bytes  type        scaling notes
28     int         +4 bytes about every 30 powers of 2
37     bytes       +1 byte per additional byte
49     str         +1-4 per additional character (depending on max width)
48     tuple       +8 per additional item
64     list        +8 for each additional
224    set         5th increases to 736; 21nd, 2272; 85th, 8416; 341, 32992
240    dict        6th increases to 368; 22nd, 1184; 43rd, 2280; 86th, 4704; 171st, 9320
136    func def    does not include default args and other attrs
1056   class def   no slots 
56     class inst  has a __dict__ attr, same scaling as dict above
888    class def   with slots
16     __slots__   seems to store in mutable tuple-like structure
                   first slot grows to 48, and so on.

Làm thế nào để bạn giải thích điều này? Vâng, nói rằng bạn có một bộ với 10 mục trong đó. Nếu mỗi mục là 100 byte, thì toàn bộ cấu trúc dữ liệu lớn đến mức nào? Bộ này là 736 vì nó có kích thước một lần lên tới 736 byte. Sau đó, bạn thêm kích thước của các mục, tổng cộng là 1736 byte

Một số cảnh báo cho các định nghĩa hàm và lớp:

Lưu ý mỗi định nghĩa lớp có __dict__cấu trúc proxy (48 byte) cho attrs lớp. Mỗi vị trí có một mô tả (như a property) trong định nghĩa lớp.

Các trường hợp có rãnh bắt đầu với 48 byte trên phần tử đầu tiên của chúng và tăng thêm 8 byte mỗi phần tử. Chỉ các đối tượng có rãnh trống mới có 16 byte và một thể hiện không có dữ liệu có ý nghĩa rất nhỏ.

Ngoài ra, mỗi định nghĩa hàm có các đối tượng mã, có thể là các tài liệu và các thuộc tính có thể khác, thậm chí là a __dict__.

Cũng lưu ý rằng chúng tôi sử dụng sys.getsizeof()vì chúng tôi quan tâm đến việc sử dụng không gian cận biên, bao gồm cả chi phí thu gom rác cho đối tượng, từ các tài liệu :

gotizeof () gọi __sizeof__phương thức của đối tượng và thêm chi phí thu gom rác bổ sung nếu đối tượng được quản lý bởi trình thu gom rác.

Cũng lưu ý rằng việc thay đổi kích thước danh sách (ví dụ như lặp đi lặp lại thêm vào chúng) khiến chúng sắp xếp lại không gian, tương tự như các tập hợp và ký tự. Từ mã nguồn listobj.c :

    /* This over-allocates proportional to the list size, making room
     * for additional growth.  The over-allocation is mild, but is
     * enough to give linear-time amortized behavior over a long
     * sequence of appends() in the presence of a poorly-performing
     * system realloc().
     * The growth pattern is:  0, 4, 8, 16, 25, 35, 46, 58, 72, 88, ...
     * Note: new_allocated won't overflow because the largest possible value
     *       is PY_SSIZE_T_MAX * (9 / 8) + 6 which always fits in a size_t.
     */
    new_allocated = (size_t)newsize + (newsize >> 3) + (newsize < 9 ? 3 : 6);

Dữ liệu lịch sử

Phân tích Python 2.7, được xác nhận với guppy.hpysys.getsizeof:

Bytes  type        empty + scaling notes
24     int         NA
28     long        NA
37     str         + 1 byte per additional character
52     unicode     + 4 bytes per additional character
56     tuple       + 8 bytes per additional item
72     list        + 32 for first, 8 for each additional
232    set         sixth item increases to 744; 22nd, 2280; 86th, 8424
280    dict        sixth item increases to 1048; 22nd, 3352; 86th, 12568 *
120    func def    does not include default args and other attrs
64     class inst  has a __dict__ attr, same scaling as dict above
16     __slots__   class with slots has no dict, seems to store in 
                   mutable tuple-like structure.
904    class def   has a proxy __dict__ structure for class attrs
104    old class   makes sense, less stuff, has real dict though.

Lưu ý rằng từ điển ( nhưng không phải bộ ) có biểu diễn nhỏ gọn hơn trong Python 3.6

Tôi nghĩ 8 byte cho mỗi mục bổ sung để tham khảo có ý nghĩa rất lớn trên máy 64 bit. 8 byte đó trỏ đến vị trí trong bộ nhớ của mục được chứa. 4 byte là chiều rộng cố định cho unicode trong Python 2, nếu tôi nhớ chính xác, nhưng trong Python 3, str trở thành một unicode có chiều rộng bằng với chiều rộng tối đa của các ký tự.

(Và để biết thêm về các vị trí, xem câu trả lời này )

Một chức năng hoàn chỉnh hơn

Chúng tôi muốn một hàm tìm kiếm các phần tử trong danh sách, bộ dữ liệu, bộ, dicts, obj.__dict__'s vàobj.__slots__ , cũng như những thứ khác mà chúng tôi có thể chưa nghĩ đến.

Chúng tôi muốn dựa vào gc.get_referentsđể thực hiện tìm kiếm này vì nó hoạt động ở cấp độ C (làm cho nó rất nhanh). Nhược điểm là get_Vferents có thể trả về các thành viên dư thừa, vì vậy chúng tôi cần đảm bảo chúng tôi không tính gấp đôi.

Các lớp, mô-đun và hàm là các singletons - chúng tồn tại một lần trong bộ nhớ. Chúng tôi không quan tâm đến kích thước của chúng, vì chúng tôi không thể làm gì nhiều về chúng - chúng là một phần của chương trình. Vì vậy, chúng tôi sẽ tránh đếm chúng nếu chúng được tham chiếu.

Chúng tôi sẽ sử dụng danh sách đen các loại vì vậy chúng tôi không bao gồm toàn bộ chương trình trong số lượng kích thước của chúng tôi.

import sys
from types import ModuleType, FunctionType
from gc import get_referents

# Custom objects know their class.
# Function objects seem to know way too much, including modules.
# Exclude modules as well.
BLACKLIST = type, ModuleType, FunctionType


def getsize(obj):
    """sum size of object & members."""
    if isinstance(obj, BLACKLIST):
        raise TypeError('getsize() does not take argument of type: '+ str(type(obj)))
    seen_ids = set()
    size = 0
    objects = [obj]
    while objects:
        need_referents = []
        for obj in objects:
            if not isinstance(obj, BLACKLIST) and id(obj) not in seen_ids:
                seen_ids.add(id(obj))
                size += sys.getsizeof(obj)
                need_referents.append(obj)
        objects = get_referents(*need_referents)
    return size

Để đối chiếu điều này với chức năng được liệt kê trong danh sách trắng sau đây, hầu hết các đối tượng đều biết cách tự di chuyển theo mục đích thu gom rác (đó là khoảng những gì chúng ta đang tìm kiếm khi chúng ta muốn biết các đối tượng nhất định đắt như thế nào. gc.get_referents .) Tuy nhiên, biện pháp này sẽ có phạm vi mở rộng hơn nhiều so với dự định của chúng tôi nếu chúng tôi không cẩn thận.

Ví dụ, các hàm biết khá nhiều về các mô-đun mà chúng được tạo.

Một điểm tương phản khác là các chuỗi là các khóa trong từ điển thường được thực hiện để chúng không bị trùng lặp. Kiểm tra id(key)cũng sẽ cho phép chúng tôi tránh đếm các bản sao, điều chúng tôi sẽ làm trong phần tiếp theo. Giải pháp danh sách đen bỏ qua các phím đếm hoàn toàn.

Các loại danh sách trắng, khách truy cập đệ quy (triển khai cũ)

Để tự mình bao quát hầu hết các loại này, thay vì dựa vào mô đun gc, tôi đã viết hàm đệ quy này để cố gắng ước tính kích thước của hầu hết các đối tượng Python, bao gồm hầu hết các nội dung, loại trong mô đun bộ sưu tập và các loại tùy chỉnh (có rãnh và mặt khác) .

Loại chức năng này cho phép kiểm soát chi tiết hơn nhiều đối với các loại chúng ta sẽ tính cho việc sử dụng bộ nhớ, nhưng có nguy cơ loại bỏ các loại:

import sys
from numbers import Number
from collections import Set, Mapping, deque

try: # Python 2
    zero_depth_bases = (basestring, Number, xrange, bytearray)
    iteritems = 'iteritems'
except NameError: # Python 3
    zero_depth_bases = (str, bytes, Number, range, bytearray)
    iteritems = 'items'

def getsize(obj_0):
    """Recursively iterate to sum size of object & members."""
    _seen_ids = set()
    def inner(obj):
        obj_id = id(obj)
        if obj_id in _seen_ids:
            return 0
        _seen_ids.add(obj_id)
        size = sys.getsizeof(obj)
        if isinstance(obj, zero_depth_bases):
            pass # bypass remaining control flow and return
        elif isinstance(obj, (tuple, list, Set, deque)):
            size += sum(inner(i) for i in obj)
        elif isinstance(obj, Mapping) or hasattr(obj, iteritems):
            size += sum(inner(k) + inner(v) for k, v in getattr(obj, iteritems)())
        # Check for custom object instances - may subclass above too
        if hasattr(obj, '__dict__'):
            size += inner(vars(obj))
        if hasattr(obj, '__slots__'): # can have __slots__ with __dict__
            size += sum(inner(getattr(obj, s)) for s in obj.__slots__ if hasattr(obj, s))
        return size
    return inner(obj_0)

Và tôi đã thử nghiệm nó khá tình cờ (tôi nên bỏ qua nó):

>>> getsize(['a', tuple('bcd'), Foo()])
344
>>> getsize(Foo())
16
>>> getsize(tuple('bcd'))
194
>>> getsize(['a', tuple('bcd'), Foo(), {'foo': 'bar', 'baz': 'bar'}])
752
>>> getsize({'foo': 'bar', 'baz': 'bar'})
400
>>> getsize({})
280
>>> getsize({'foo':'bar'})
360
>>> getsize('foo')
40
>>> class Bar():
...     def baz():
...         pass
>>> getsize(Bar())
352
>>> getsize(Bar().__dict__)
280
>>> sys.getsizeof(Bar())
72
>>> getsize(Bar.__dict__)
872
>>> sys.getsizeof(Bar.__dict__)
280

Việc triển khai này phá vỡ các định nghĩa lớp và định nghĩa hàm vì chúng ta không theo đuổi tất cả các thuộc tính của chúng, nhưng vì chúng chỉ tồn tại một lần trong bộ nhớ cho quy trình, nên kích thước của chúng thực sự không quá quan trọng.


5
Bạn có thể thêm rằng câu trả lời này là dành riêng cho CPython (được ngụ ý là bạn nhận Python thông qua Anaconda)
gerrit

1
CPython là triển khai tham chiếu và tôi vừa xem xét các tài liệu trực tuyến của jython cung cấp cùng API, vì vậy tôi tin rằng điều này sẽ hoạt động trên các triển khai khác, miễn là chúng triển khai API.
Aaron Hall

đối với tôi đã không làm việc cho các mảng numpy bị che khuất và lột mặt nạ stackoverflow.com/q/58675479/2132157
GM

95

Các Pympler gói của asizeofmô-đun có thể làm điều này.

Sử dụng như sau:

from pympler import asizeof
asizeof.asizeof(my_object)

Không giống như sys.getsizeof, nó hoạt động cho các đối tượng tự tạo của bạn . Nó thậm chí hoạt động với numpy.

>>> 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
>>> A = rand(10)
>>> B = rand(10000)
>>> asizeof.asizeof(A)
176
>>> asizeof.asizeof(B)
80096

Như đã đề cập ,

Kích thước mã (byte) của các đối tượng như các lớp, hàm, phương thức, mô-đun, v.v. có thể được bao gồm bởi tùy chọn cài đặt code=True.

Và nếu bạn cần một cái nhìn khác về dữ liệu trực tiếp, Pympler's

mô-đun muppyđược sử dụng để giám sát trực tuyến một ứng dụng Python và mô-đun Class Trackercung cấp phân tích ngoại tuyến về thời gian tồn tại của các đối tượng Python được chọn.


chức năng này khá chậm đối với các đối tượng lớn hơn. Có tồn tại một tương đương "nhanh" hoạt động cho các đối tượng tự tạo không?
Shuklaswag

Tôi chưa thử nó, nhưng org.apache.spark.util.SizeEstimatorcó thể có liên quan
Shuklaswag

1
@Shuklaswag: nếu bạn sử dụng tia lửa, nó có thể là như vậy. Bạn có nghĩ rằng ước tính chuyển đổi + Java nhanh hơn các phương thức dựng sẵn của python không? Hay tôi đã hiểu lầm?
phục vụ

3
Có thể đáng chú ý là pymplercó khả năng đưa kích thước mã thực thi của các hàm và các đối tượng mã và đối tượng mã khác vào tài khoản.
mtraceur

Tôi nhận được một TypeErrorngoại lệ: "Đối tượng noneType" không thể gọi được "bất cứ khi nào đối tượng tùy chỉnh của tôi có một số tiểu dự án trong" cây "có giá trị None. Có cách giải quyết nhanh nào cho việc này không?
James Hirschorn

81

Đối với mảng numpy, getsizeofkhông hoạt động - đối với tôi, nó luôn trả về 40 vì một số lý do:

from pylab import *
from sys import getsizeof
A = rand(10)
B = rand(10000)

Sau đó (trong ipython):

In [64]: getsizeof(A)
Out[64]: 40

In [65]: getsizeof(B)
Out[65]: 40

Hạnh phúc, mặc dù:

In [66]: A.nbytes
Out[66]: 80

In [67]: B.nbytes
Out[67]: 80000

29
> Tất cả các đối tượng tích hợp sẽ trả về kết quả chính xác, nhưng điều này không phải đúng với các tiện ích mở rộng của bên thứ ba vì nó là triển khai cụ thể. docs.python.org/library/sys.html#sys.getsizeof
warvariuc

33
"Nếu bạn đang sử dụng một mảng numpy ( docs.scipy.org/doc/numpy/reference/arrays.ndarray.html ) thì bạn có thể sử dụng thuộc tính 'ndarray.nbytes' để đánh giá kích thước của nó trong bộ nhớ." stackoverflow.com/a/15591157/556413
glarrain

17
Tôi đoán 40 byte là chính xác, tuy nhiên getsizeof()chỉ cung cấp cho bạn kích thước của đối tượng (tiêu đề của mảng), không phải của dữ liệu bên trong. Tương tự đối với các thùng chứa trăn ở đâu sys.getsizeof([1,2,4]) == sys.getsizeof([1,123**456,4]) == 48, trong khisys.getsizeof(123**456) = 436
yota

3
Có vẻ như getsizeof()chức năng đã được thay đổi tại một số điểm để trả về giá trị mong đợi.
dshin

14

Điều này có thể phức tạp hơn vẻ ngoài của nó tùy thuộc vào cách bạn muốn đếm mọi thứ. Ví dụ: nếu bạn có một danh sách các số nguyên, bạn có muốn kích thước của danh sách chứa các tham chiếu đến các số nguyên không? (ví dụ: chỉ liệt kê, không chứa những gì có trong đó) hoặc bạn muốn bao gồm dữ liệu thực tế được chỉ đến, trong trường hợp đó bạn cần xử lý các tham chiếu trùng lặp và cách ngăn chặn tính hai lần khi hai đối tượng chứa tham chiếu đến cùng một đối tượng.

Bạn có thể muốn xem một trong những trình biên dịch bộ nhớ python, chẳng hạn như pysizer để xem chúng có đáp ứng nhu cầu của bạn không.


14

Python 3.8 (Q1 2019) sẽ thay đổi một số kết quả sys.getsizeof, như được công bố tại đây bởi Raymond Hettinger:

Các thùng chứa Python nhỏ hơn 8 byte trên các bản dựng 64 bit.

tuple ()  48 -> 40       
list  []  64 ->56
set()    224 -> 216
dict  {} 240 -> 232

Điều này xuất hiện sau sự cố 33597 và công việc của Inada Naoki ( methane) xung quanh Compact PyGC_Head và PR 7043

Ý tưởng này làm giảm kích thước PyGC_Head xuống còn hai từ .

Hiện tại, PyGC_Head mất ba từ ; gc_prev, gc_next, Và gc_refcnt.

  • gc_refcnt được sử dụng khi thu thập, để xóa thử nghiệm.
  • gc_prev được sử dụng để theo dõi và không theo dõi.

Vì vậy, nếu chúng ta có thể tránh theo dõi / không theo dõi trong khi xóa bản dùng thử gc_prevgc_refcntcó thể chia sẻ cùng một không gian bộ nhớ.

Xem cam kết d5c875b :

Đã xóa một Py_ssize_tthành viên khỏi PyGC_Head.
Tất cả các đối tượng được theo dõi của GC (ví dụ: tuple, list, dict) được giảm 4 hoặc 8 byte.


10

Bản thân tôi đã gặp phải vấn đề này nhiều lần, tôi đã viết ra một chức năng nhỏ (lấy cảm hứng từ câu trả lời của @ aaron-hall) & kiểm tra những gì tôi mong đợi sys.getsizeof sẽ làm:

https://github.com/bosswissam/pysize

Nếu bạn quan tâm đến câu chuyện hậu trường, thì đây là

EDIT: Đính kèm mã dưới đây để tham khảo dễ dàng. Để xem mã cập nhật nhất, vui lòng kiểm tra liên kết github.

    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

7

Đây là một kịch bản nhanh mà tôi đã viết dựa trên các câu trả lời trước để liệt kê kích thước của tất cả các biến

for i in dir():
    print (i, sys.getsizeof(eval(i)) )

Nó không sai, nó mơ hồ. sys.getsizeof sẽ luôn trả về giá trị là cần thiết, do đó không cần mất hiệu năng với try..except.
der_fenix

ồ, đó là một điểm tốt và tôi đã không nghĩ về nó - mã ở dạng hiện tại chỉ cho thấy cách nó được viết theo trình tự thời gian - đầu tiên tôi biết về numpy (do đó là nbyte), sau đó tôi tìm kiếm một giải pháp chung chung hơn . Cảm ơn bạn đã giải thích _ / \ _
alexey

7

Bạn có thể tuần tự hóa đối tượng để rút ra một thước đo có liên quan mật thiết đến kích thước của đối tượng:

import pickle

## let o be the object, whose size you want to measure
size_estimate = len(pickle.dumps(o))

Nếu bạn muốn đo các đối tượng không thể được chọn (ví dụ vì biểu thức lambda) thì có thể là một giải pháp.


4

Sử dụng sys.getsizeof () nếu bạn không muốn bao gồm kích thước của các đối tượng được liên kết (lồng nhau).

Tuy nhiên, nếu bạn muốn đếm các đối tượng phụ được lồng trong danh sách, dicts, sets, tuples - và thường thì đây là thứ bạn đang tìm kiếm - hãy sử dụng hàm sizeof () đệ quy sâu như hình dưới đây:

import sys
def sizeof(obj):
    size = sys.getsizeof(obj)
    if isinstance(obj, dict): return size + sum(map(sizeof, obj.keys())) + sum(map(sizeof, obj.values()))
    if isinstance(obj, (list, tuple, set, frozenset)): return size + sum(map(sizeof, obj))
    return size

Bạn cũng có thể tìm thấy chức năng này trong hộp công cụ tiện lợi , cùng với nhiều lớp lót hữu ích khác:

https://github.com/mwojnars/nifty/blob/master/util.py


3

Nếu bạn không cần kích thước chính xác của vật thể nhưng đại khái là để biết nó lớn như thế nào, một cách nhanh chóng (và bẩn) là để chương trình chạy, ngủ trong một khoảng thời gian dài và kiểm tra mức sử dụng bộ nhớ (ví dụ : Trình giám sát hoạt động của Mac) theo quy trình trăn cụ thể này. Điều này sẽ có hiệu quả khi bạn đang cố gắng tìm kích thước của một vật thể lớn duy nhất trong một quy trình python. Ví dụ, gần đây tôi muốn kiểm tra mức sử dụng bộ nhớ của cấu trúc dữ liệu mới và so sánh nó với cấu trúc dữ liệu đã đặt của Python. Đầu tiên tôi viết các phần tử (các từ trong một cuốn sách miền công cộng lớn) vào một tập hợp, sau đó kiểm tra kích thước của quy trình và sau đó thực hiện tương tự với cấu trúc dữ liệu khác. Tôi phát hiện ra quy trình Python với một bộ đang chiếm gấp đôi bộ nhớ so với cấu trúc dữ liệu mới. Một lần nữa, bạn sẽ không t có thể nói chính xác bộ nhớ được sử dụng bởi quá trình này bằng với kích thước của đối tượng. Khi kích thước của đối tượng trở nên lớn, điều này trở nên gần gũi khi bộ nhớ được sử dụng bởi phần còn lại của quá trình trở nên không đáng kể so với kích thước của đối tượng bạn đang cố gắng theo dõi.


1
Câu hỏi hỏi làm thế nào để thực hiện nó trong python , không chỉ là tìm cách sử dụng bộ nhớ của các đối tượng python và sử dụng trình giám sát hoạt động của Mac hoặc bất kỳ phần mềm tương tự nào khác không được lập trình bằng python. Điều đó đang được nói, kiểm tra việc sử dụng bộ nhớ của các quá trình python theo cách này nói chung là một cách tốt để đảm bảo không có gì sai ...
Tom Wyllie

@TomWyllie, Cảm ơn, nhưng hạ thấp câu trả lời này mang ý nghĩa tiêu cực rằng bản thân câu trả lời là sai và không thực hiện được gì. Phương thức tôi đề cập có thể không được triển khai trong Python, nhưng nó là một cách thuận tiện để có được ước tính sơ bộ về kích thước của một đối tượng Python. Tôi biết tôi không trả lời chính xác câu hỏi, tuy nhiên, phương pháp này có thể hữu ích cho người khác để có được kết quả tương tự.
picmate

1

Bạn có thể sử dụng getSizeof () như được đề cập dưới đây để xác định kích thước của một đối tượng

import sys
str1 = "one"
int_element=5
print("Memory size of '"+str1+"' = "+str(sys.getsizeof(str1))+ " bytes")
print("Memory size of '"+ str(int_element)+"' = "+str(sys.getsizeof(int_element))+ " bytes")

0

Tôi sử dụng thủ thuật này ... Có thể sẽ không chính xác trên các đối tượng nhỏ, nhưng tôi nghĩ nó chính xác hơn nhiều đối với một đối tượng phức tạp (như bề mặt pygame) thay vì sys.getsizeof ()

import pygame as pg
import os
import psutil
import time


process = psutil.Process(os.getpid())
pg.init()    
vocab = ['hello', 'me', 'you', 'she', 'he', 'they', 'we',
         'should', 'why?', 'necessarily', 'do', 'that']

font = pg.font.SysFont("monospace", 100, True)

dct = {}

newMem = process.memory_info().rss  # don't mind this line
Str = f'store ' + f'Nothing \tsurface use about '.expandtabs(15) + \
      f'0\t bytes'.expandtabs(9)  # don't mind this assignment too

usedMem = process.memory_info().rss

for word in vocab:
    dct[word] = font.render(word, True, pg.Color("#000000"))

    time.sleep(0.1)  # wait a moment

    # get total used memory of this script:
    newMem = process.memory_info().rss
    Str = f'store ' + f'{word}\tsurface use about '.expandtabs(15) + \
          f'{newMem - usedMem}\t bytes'.expandtabs(9)

    print(Str)
    usedMem = newMem

Trên windows 10 của tôi, python 3.7.3, đầu ra là:

store hello          surface use about 225280    bytes
store me             surface use about 61440     bytes
store you            surface use about 94208     bytes
store she            surface use about 81920     bytes
store he             surface use about 53248     bytes
store they           surface use about 114688    bytes
store we             surface use about 57344     bytes
store should         surface use about 172032    bytes
store why?           surface use about 110592    bytes
store necessarily    surface use about 311296    bytes
store do             surface use about 57344     bytes
store that           surface use about 110592    bytes
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.