记忆消耗和临时生活

时间:2012-12-09 12:58:47

标签: 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. new_list中创建的tweak_list的有效期是多少?它会在退出时被销毁,还是会被垃圾收集(此时?)。对tweak_list的重复呼叫是否会在很长一段时间内产生大量的小名单?
  2. list转换为tuple以用作dict密钥时是否有临时创建?
  3. dict设置为空的会释放内存吗?
  4. 或者,我是从一个完全错误的角度来处理手头的问题吗?

2 个答案:

答案 0 :(得分:4)

    当没有返回函数时,
  1. new_lst被清除。它的引用计数降为0,可以进行垃圾回收。关于当前发生的cpython实现。

    如果 返回,new_lst引用的值将替换lst; lst引用的列表看到它的引用计数下降1,但new_lst最初引用的值仍由另一个变量引用。

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

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

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

答案 1 :(得分:0)

您可能需要查看Heapy作为分析内存使用情况的方法。我认为PySizer在某些情况下也用于此,但我不熟悉它。 ObjGraph也是一个很好的工具。