我正在尝试诊断内存泄漏。通过使用pympler
和objgraph
等工具,我可以看到在我的程序代码中主循环的每次迭代之后添加了许多大型列表。这是意外的行为 - 程序启动后列表的数量应该保持不变,而不是在循环中增长。
我想查看每次迭代后添加的列表。我试图通过类似于以下(非常简化的)代码的方式来做到这一点:
def my_func():
import objgraph
import gc
existing = objgraph.by_type("list")
for item in to_do():
gc.collect()
new = objgraph.by_type('list')
diff = [item for item in new if item not in existing]
existing = new
do_something(item)
但是,当我尝试这个时,我收到以下错误:
RuntimeError: maximum recursion depth exceeded in comparison
我理解为什么会这样,但我仍然需要一种方法来调查新列表。如何才能访问这些新列表以便我可以调查内存泄漏?
答案 0 :(得分:1)
正如您所知,使用item not in existing
会因为它检查相等性(例如a == b
)而需要遍历嵌套结构。然而,平等实际上并不是我们首先感兴趣的。相反,我们想要比较身份,即a is b
。这样便宜得多,因为它与对象内容无关。
作为列表理解,我们可以说
diff = [n for e in existing for n in new if n is e]
这是相当浪费的,因为即使我们找到匹配项,我们也会继续搜索所有existing
。
def is_in(item, collection):
for c in collection:
if item is c:
return True
return False
diff = [item for item in new if not is_in(item, existing)]
最快的解决方案应该是在existing
中获取一次身份并将它们放入一组以便更有效地搜索:
existing_ids = {id(item) for item in existing}
diff = [item for item in new if id(item) in existing_ids]
答案 1 :(得分:0)
使用API调试器,例如与PyCharm一起来的那个。 在迭代中的合理点设置断点,并逐步执行。