1

我有一个 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. new_list在 a 中创建的 a的生命周期是tweak_list多少?它会在退出时被销毁,还是会被垃圾收集(此时?)。是否会反复调用tweak_list生成大量的小列表而长时间徘徊?
  2. list将 a 转换为 atuple以用作dict密钥时是否有临时创建?
  3. 将a设置dict为空会释放内存吗?
  4. 或者,我是从一个完全错误的角度来处理手头的问题吗?
4

2 回答 2

4
  1. new_lst当函数存在时被清理而不返回。它的引用计数下降到 0,它可以被垃圾收集。在立即发生的当前 cpython 实现上。

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

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

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

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

于 2012-12-09T13:18:19.480 回答
0

您可能希望将Heapy视为一种分析内存使用情况的方法。我认为PySizer在某些情况下也用于此目的,但我不熟悉它。ObjGraph也是一个强大的工具来看看。

于 2012-12-09T13:10:36.103 回答