深度版的sys.getsizeof函数

13

我想计算一个对象使用的内存。sys.getsizeof很好,但它是浅层次的(例如,如果应用于列表,则不包括列表元素占用的内存)。

我想编写一个通用的“深层次”版本的sys.getsizeof。我理解“深层次”一词的定义有些模糊;我完全满意 copy.deepcopy所遵循的定义

这是我的第一次尝试:

def get_deep_sizeof(x, level=0, processed=None):
    if processed is None:
        # we're here only if this function is called by client code, not recursively
        processed = set()
    processed.add(id(x))
    mem = sys.getsizeof(x)
    if isinstance(x, collections.Iterable) and not isinstance(x, str):
        for xx in x:
            if id(xx) in processed:
                continue
            mem += get_deep_sizeof(xx, level+1, processed)
            if isinstance(x, dict):
                mem += get_deep_sizeof(x[xx], level+1, processed)
    return mem

它有两个已知问题和未知数量的未知问题:

  • 我不知道如何以捕获所有链接对象的方式遍历通用容器。因此,我使用了in进行迭代,并硬编码字典的情况(以包括值,而不仅仅是键)。显然,这对于像字典之类的其他类是无效的。
  • 我不得不硬编码排除str(它是可迭代的,但没有链接到任何其他对象)。同样,如果有更多类似的对象,则会出现问题。

我怀疑使用in不是一个好主意,但我不确定还能做什么。


啊,这是一个重复的问题,与https://dev59.com/rG445IYBdhLWcg3wIGx9和https://dev59.com/dHM_5IYBdhLWcg3wjj0p相同。 - max
1个回答

14

我认为 Pympler 已经在这方面先行一步了。

根据他们的文档

>>> from pympler.asizeof import asizeof
>>> obj = [1, 2, (3, 4), 'text']
>>> asizeof(obj)
176

源代码可以在这里找到。


3
看起来很不错。然而,似乎没有优雅的解决方案来解决这个问题;pympler 在硬编码 dict(并允许注册其他类别被视为 dict)。我不知道为什么迭代所有属性(除了那些特别排除的属性)不起作用... - max

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接