Python集花费的内存量逐步增加

时间:2018-10-16 08:26:19

标签: python numpy

我做了一个实验,研究每种Python数组类型消耗多少内存,分别是listtuplesetdictnp.array。然后我得到了以下结果。

The amount of memory Python array types spend

(x轴是数组的长度,y轴是内存大小。)

我发现Python set花费的内存量逐步增加(也dict),而其他的则按我的预期线性增加。我想知道是什么让他们与众不同。

我使用了以下get_size()函数。 (reference

def get_size(obj, seen = None):
    size = sys.getsizeof(obj)
    if seen is None:
        seen = set()
    obj_id = id(obj)
    if obj_id in seen:
        return 0
    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

然后我以100个间隔测量了从0到10,000长度的内存。

我的代码:https://repl.it/repls/WanEsteemedLines

1 个答案:

答案 0 :(得分:3)

CPython集合和字典始终使用2的幂的内部哈希表。 listtuplenumpy.ndarray在其基础内存缓冲区的大小方面都具有更大的灵活性,但是setdict被硬编码为使用强大的功能-两种尺寸的桌子。该实现无法以非2的幂的表大小运行。参见Objects/dictobject.cObjects/setobject.c

图表中的跳转是表大小跳转到新的2的幂时。

偶然地,您的get_size不能很好地工作。例如,它有两个影响numpy.ndarray情况的错误,这些错误几乎被抵消了(但不完全相同)。它尝试将NumPy数组的元素大小添加到整个数组的大小,但是对于NumPy数组,元素的大小已经由getsizeof所占。另外,它使用id确定对象的身份,但是通过迭代NumPy数组而生成的对象是即时创建并立即死亡的,因此它们的id值不是唯一的。在实践中,这可能会使大小超出代表数组元素的对象大小的一到两倍。