度量对象准确地在Python大小 - Sys.GetSizeOf不正常度量对象准确地在Python

2019-06-14 12:45发布

我试图精确/确切找到Python中两个不同阶级之间的大小差异。 他们都是新样式类,除定义了一个没有缝隙 。 我已经试过无数次的测试,以确定它们的大小差异,但他们总是最终被在内存使用情况相同。

到目前为止,我已经尝试sys.GetSizeOf(OBJ)和heapy的堆()函数,没有阳性结果。 测试代码如下:

import sys
from guppy import hpy

class test3(object):
    def __init__(self):
        self.one = 1
        self.two = "two variable"

class test4(object):
    __slots__ = ('one', 'two')
    def __init__(self):
        self.one = 1
        self.two = "two variable"

test3_obj = test3()
print "Sizeof test3_obj", sys.getsizeof(test3_obj)

test4_obj = test4()
print "Sizeof test4_obj", sys.getsizeof(test4_obj)

arr_test3 = []
arr_test4 = []

for i in range(3000):
    arr_test3.append(test3())
    arr_test4.append(test4())

h = hpy()
print h.heap()

输出:

 Sizeof test3_obj 32 Sizeof test4_obj 32 Partition of a set of 34717 objects. Total size = 2589028 bytes. Index Count % Size % Cumulative % Kind (class / dict of class) 0 11896 34 765040 30 765040 30 str 1 3001 9 420140 16 1185180 46 dict of __main__.test3 2 5573 16 225240 9 1410420 54 tuple 3 348 1 167376 6 1577796 61 dict (no owner) 4 1567 5 106556 4 1684352 65 types.CodeType 5 68 0 105136 4 1789488 69 dict of module 6 183 1 97428 4 1886916 73 dict of type 7 3001 9 96032 4 1982948 77 __main__.test3 8 3001 9 96032 4 2078980 80 __main__.test4 9 203 1 90360 3 2169340 84 type <99 more rows. Type eg '_.more' to view.> 

这是所有与Python 2.6.0。 我也试图覆盖类的方法的sizeof试图通过个人sizeofs相加确定大小,但没有取得任何不同的结果:

class test4(object):
    __slots__ = ('one', 'two')
    def __init__(self):
        self.one = 1
        self.two = "two variable"
    def __sizeof__(self):
        return super(test4, self).__sizeof__() + self.one.__sizeof__() + self.two.__sizeof__()

结果与覆盖了的sizeof方法:

 Sizeof test3_obj 80 Sizeof test4_obj 80 

Answer 1:

sys.getsizeof返回一个数字是专业化,比人们想象的那么有用。 事实上,如果你增加属性数量到六,你test3_obj仍为32,但test4_obj跳转到48个字节。 这是因为getsizeof将返回执行的类型,这对于test3_obj不包括字典保持的属性,但对于test4_obj,属性不存储在一个字典中的PyObject结构的大小,它们被存储在槽中,所以他们占规模。

但随着中定义的类__slots__花费较少的内存比无类,正是因为没有字典持有的属性。

为什么覆盖__sizeof__ ? 什么是你真正想要实现?



Answer 2:

正如其他人所指出的, sys.getsizeof只返回一个代表你的数据对象结构的大小。 所以,如果,例如,您有不断添加元素,动态数组, sys.getsizeof(my_array)将只显示基地规模DynamicArray对象,而不是内存的规模不断壮大,它的元素占用。

pympler.asizeof.asizeof()给出的物体的大致完整的规模和可能对你更准确。

from pympler import asizeof
asizeof.asizeof(my_object)  # should give you the full object size


Answer 3:

首先检查你的OS'内存管理器的进程Pyton的大小没有太多的对象。

其次使1种许多对象,并再次检查大小。

三是使其他种类的许多对象和检查大小。

这重复了几次,如果每一步的大小大致不变,你已经得到的东西相媲美。



Answer 4:

我遇到了类似的问题,最终写我自己的帮手做肮脏的工作。 检查出来这里



Answer 5:

您可能需要使用不同的实现让你的对象的大小在内存中:

>>> import sys, array
>>> sizeof = lambda obj: sum(map(sys.getsizeof, explore(obj, set())))
>>> def explore(obj, memo):
    loc = id(obj)
    if loc not in memo:
        memo.add(loc)
        yield obj
        if isinstance(obj, memoryview):
            yield from explore(obj.obj, memo)
        elif not isinstance(obj, (range, str, bytes, bytearray, array.array)):
            # Handle instances with slots.
            try:
                slots = obj.__slots__
            except AttributeError:
                pass
            else:
                for name in slots:
                    try:
                        attr = getattr(obj, name)
                    except AttributeError:
                        pass
                    else:
                        yield from explore(attr, memo)
            # Handle instances with dict.
            try:
                attrs = obj.__dict__
            except AttributeError:
                pass
            else:
                yield from explore(attrs, memo)
            # Handle dicts or iterables.
            for name in 'keys', 'values', '__iter__':
                try:
                    attr = getattr(obj, name)
                except AttributeError:
                    pass
                else:
                    for item in attr():
                        yield from explore(item, memo)


>>> class Test1:
    def __init__(self):
        self.one = 1
        self.two = 'two variable'


>>> class Test2:
    __slots__ = 'one', 'two'
    def __init__(self):
        self.one = 1
        self.two = 'two variable'


>>> print('sizeof(Test1()) ==', sizeof(Test1()))
sizeof(Test1()) == 361
>>> print('sizeof(Test2()) ==', sizeof(Test2()))
sizeof(Test2()) == 145
>>> array_test1, array_test2 = [], []
>>> for _ in range(3000):
    array_test1.append(Test1())
    array_test2.append(Test2())


>>> print('sizeof(array_test1) ==', sizeof(array_test1))
sizeof(array_test1) == 530929
>>> print('sizeof(array_test2) ==', sizeof(array_test2))
sizeof(array_test2) == 194825
>>> 

只要确保你,如果你想要一个答案回不给任何无限迭代器的代码。



文章来源: Measure Object Size Accurately in Python - Sys.GetSizeOf not functioning