Python在垃圾收集上花费了过多的时间
我正在处理一段复杂的python代码,它将大约40%的执行时间用于垃圾收集Python在垃圾收集上花费了过多的时间,python,pandas,garbage-collection,performance-testing,Python,Pandas,Garbage Collection,Performance Testing,我正在处理一段复杂的python代码,它将大约40%的执行时间用于垃圾收集 ncalls tottime percall cumtime percall filename:lineno(function) **6028 494.097 0.082 494.097 0.082** {built-in method gc.collect} 1900 205.709 0.108 205.709 0.108 {built-in method time
ncalls tottime percall cumtime percall filename:lineno(function)
**6028 494.097 0.082 494.097 0.082** {built-in method gc.collect}
1900 205.709 0.108 205.709 0.108 {built-in method time.sleep}
778 26.858 0.035 383.476 0.493 func1.py:51(fill_trades)
有没有办法减少对gc.collect的调用数量?我尝试了gc.disable(),但它的有效性受到限制,因为Cpython主要使用引用计数。我正在使用python 3.6 如果没有看到代码,就不可能正确回答。不过,您可以使用一些通用技巧来改善这种情况 主要的一点是:限制分配的数量。您是否经常在小包装中重新包装一些无用的值?你经常复制字符串的一部分吗?您是否在执行大量复制数据的消息解析?找出最常分配内存的内容并加以改进。这可能会有帮助 针对具体情况的修复:
- 你做了很多数学密集型的运算吗?也许移动到类似于
的东西会有所帮助,因为您可以使用真实的、可变的、类型化的数组而不是列表numpy
- 你有很多数据处理代码吗?您可以使用
对其上的类型进行注释并编译模块,以消除将值包装到python对象中的需要cython
- 对于原始内存(解析/文件处理/…),您可以使用
s保存一些分配:memoryview
time.sleep
。如果您的gc.collect
占用运行时间的40%,那么time.sleep
占用16%——为什么不在此时触发收集呢?不管怎样,你还是在睡觉
编辑:另外,我确信你在某处明确地调用了gc.collect
。呼叫不会自动出现在pstats
输出上。要查找位置,请尝试:
your_pstats_object.print_callers('gc.collect')
我遇到了类似的问题,我的代码90%的时间都花在垃圾收集上。在测试中,我的函数每次调用大约需要90毫秒,但在生产中,每次调用大约需要1秒。我通过CopyWarning查看了pandas的
设置的安静形式
在我的例子中,我创建了一个数据帧的切片,如df=pd.dataframe(data)[fieldlist]
,然后分配了一个新列df['foo']=…
。此时,df.\u is\u copy
显示我们对原始数据帧有一个weakref,因此当我们调用它时,它会执行一个完整的垃圾收集周期来杀死weakref
在生产环境中,我的代码试图每秒调用该函数几次,缓存中有大量大型对象(dict),因此垃圾收集周期非常昂贵。首先确保我没有创建副本,性能几乎提高了15倍,从而修复了此问题:-您能发布一些代码吗?很难说为什么你的代码会频繁地触发垃圾收集而没有看到它,或者是一个与你的真实代码非常相似的可复制的示例。我不是手动调用gc.collect。这是pstats的输出。代码太大,无法在此处发布。代码严重依赖对象。如果有人能够在没有看到任何代码的情况下回答这个问题,我会感到惊讶。带a的问题更有可能得到答案。尤其是像这样复杂的事情,“严重依赖对象”。这就是垃圾收集器工作如此努力的原因。谢谢你的建议。谢谢你的建议。pandas调用了gc.collect()。经过一些搜索,我发现pd.set_选项('mode.chained_assignment',None)可以禁用pandas中对gc.collect的显式调用