临时存储器的内存消耗和寿命

2024-06-16 08:53:53 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个python代码,其中内存消耗随着时间的推移而稳步增长。虽然有几个对象可以合法地增长相当大,但我试图了解我观察到的内存占用是由于这些对象,还是只是我把内存与没有得到适当处理的临时内存一起乱扔——这是一个最近从手动内存管理世界转变过来的人,我想我只是不太了解python运行时如何处理临时对象的一些非常基本的方面。你知道吗

考虑一个大致具有这种一般结构的代码(我省略了不相关的细节):

def tweak_list(lst):
    new_lst = copy.deepcopy(lst)
    if numpy.random.rand() > 0.5:
        new_lst[0] += 1  # in real code, the operation is a little more sensible :-)
        return new_lst
    else:
        return lst


lst = [1, 2, 3]
cache = {}

# main loop
for step in xrange(some_large_number):

    lst = tweak_list(lst)    # <<-----(1)

    # do something with lst here, cut out for clarity

    cache[tuple(lst)] = 42   # <<-----(2)

    if step%chunk_size == 0:
        # dump the cache dict to a DB, free the memory (?)
        cache = {}           # <<-----(3)

问题:

  1. tweak_list中创建的new_list的生存期是多少?它会在出口被销毁,还是会被垃圾收集(在哪一点?)。对tweak_list的重复调用是否会产生大量的小列表,这些小列表会在很长一段时间内挥之不去?你知道吗
  2. list转换为tuple以用作dict键时是否有临时创建?你知道吗
  3. dict设置为空会释放内存吗?你知道吗
  4. 或者,我是不是从一个完全错误的角度来看待眼前的问题?你知道吗

Tags: the对象内存代码incachenewfor
2条回答
  1. new_lst在函数存在且未返回时被清除。它的引用计数下降到0,并且可以被垃圾收集。在当前的cpython实现中,这种情况会立即发生。你知道吗

    如果它返回,new_lst引用的值替换了lstlst引用的列表看到它的引用计数下降了1,但是new_lst最初引用的值仍然被另一个变量引用。

  2. tuple()键是存储在dict中的值,因此这不是临时的。除了该元组之外,不会创建其他对象。

  3. 用新的dict替换旧的cachedict将使引用计数减少1。如果cache是dict的唯一引用,它将被垃圾收集。然后,这将导致包含的所有元组键的引用计数减少1。如果没有其他引用,这些将被垃圾收集。

  4. 请注意,当Python释放内存时,并不一定意味着操作系统会立即回收内存。大多数操作系统只会在需要内存做其他事情时才回收内存,而不是假定程序可能很快又需要部分或全部内存。

您可能希望将Heapy作为分析内存使用情况的一种方法。我认为PySizer在某些情况下也用于此,但我不熟悉它。ObjGraph也是一个很好的工具。你知道吗

相关问题 更多 >