我有一个 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)
问题:
- 在
tweak_list
中创建的new_list
的生命周期是多少?它会在退出时被销毁,还是会被垃圾收集(在哪一点?)。重复调用tweak_list
是否会生成大量长期存在的小列表? - 将
list
转换为tuple
以用作dict
键时是否有临时创建? - 将
dict
设置为空是否会释放内存? - 或者,我是不是从一个完全错误的角度来处理手头的问题?
最佳答案
new_lst
未返回时函数存在时清理。它的引用计数降为 0,可以进行垃圾回收。在当前的 cpython 实现中立即发生。如果返回,
new_lst
引用的值将替换lst
;lst
引用的列表看到它的引用计数减少了 1,但是new_lst
最初引用的值仍然被另一个变量引用。tuple()
键是存储在dict
中的值,因此这不是临时值。除了那个元组之外,没有创建额外的对象。将旧的
cache
dict 替换为新的将减少一个引用计数。如果cache
是对 dict 的唯一引用,它将被垃圾收集。这会导致所有包含的元组键的引用计数减一。如果没有其他引用,那些将被垃圾收集。请注意,当 Python 释放内存时,并不一定意味着操作系统会立即回收它。大多数操作系统只会在其他需要时回收内存,而不是假设程序可能很快再次需要部分或全部内存。
关于python - 临时对象的内存消耗和生命周期,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13787549/