垃圾收集器正在使用多少时间?

9
我的Python程序有一个奇怪的性能问题:它运行得越久,就越慢。在开始时,它每分钟可以处理数十个工作单元。一小时后,每个工作单元需要花费数十分钟的时间。我的猜测是这是由于拥挤的垃圾收集器引起的。
问题在于我的脚本对内存需求过大,无法在大型运行中使用cProfile进行工作(参见:cProfile taking a lot of memory)。
我们编写了自己的性能插件,我们可以观察到我们系统的大多数部分,但似乎没有任何问题。唯一未解决的问题就是GC。
除了使用profile或cProfile之外,是否有其他方法可以查看有多少时间用于GC?
1个回答

9
在Python中,大多数垃圾使用引用计数进行收集。人们期望这是快速和无痛的,而且似乎不太可能是你想要的。我假设您正在询问gc模块所引用的收集器,该收集器仅用于循环引用。
有一些可能会有用的事情:http://docs.python.org/library/gc.html 尽管似乎没有直接方法来计时垃圾收集器,但您可以打开和关闭它,启用调试,查看收集计数等。所有这些都可能对您的探索有所帮助。
例如,在我的系统上,如果您打开调试标志,gc将打印出经过的时间:
In [1]: import gc

In [2]: gc.set_debug(gc.DEBUG_STATS)

In [3]: gc.collect()
gc: collecting generation 2...
gc: objects in each generation: 159 2655 7538
gc: done, 10 unreachable, 0 uncollectable, 0.0020s elapsed.

除此之外,我首先会关注程序运行时内存使用情况的演变。可能的情况是它仅仅到达了可用物理内存的极限,并因过多页面错误而变慢,而不是与垃圾收集器有关的任何问题。

是的,我知道。这些可以告诉我垃圾收集器正在处理多少内容,但我现在遇到的问题是处理器周期,而不是内存。如果它可以告诉我GC使用的时间甚至运行的频率,那可能会有所帮助。 - Matthew Scouten
@Matthew:你的进程调用gc.collect()本身,然后计时返回时间,这样有帮助吗? - Thomas K
@Thomas K,这会告诉我单个集合需要多长时间,但不会告诉我收集器运行的频率。鉴于我拥有的其他数据,我怀疑随着系统运行,GC 运行的次数越来越多(效果越来越小)。 - Matthew Scouten
@Matthew Scouten:请查看我的答案。如果您打开 gc.DEBUG_STATS,那么每次回收器运行时,它都会打印出一条消息,并显示每个调用的经过时间。 - NPE
@Matthew Scouten:或者,关闭它并查看是否有任何更改(正如我的答案所暗示的那样)。 - NPE
@aix 很有趣。是否有一种方法将此信息重定向到日志对象或文件?或者以编程方式访问它?如果可以将其隔离在单独的文件中,可能带有时间戳和其他上下文,那么它将非常有用。 - Matthew Scouten

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接