Python - 垃圾收集非常慢,无法禁用 gc

Posted

技术标签:

【中文标题】Python - 垃圾收集非常慢,无法禁用 gc【英文标题】:Python - Garbage collection very slow, can't disable gc 【发布时间】:2019-06-18 13:55:43 【问题描述】:

我正在开发一个使用pandas 数据框和大型字典的程序。数据帧是从大约 CSV 中读取的。 700MB。

我在 Windows 上使用 Python 3.7.3

我注意到我正在运行的程序非常慢,并且在算法的每个循环之后都会变慢。

程序读取数据帧的每一行,检查df每一行的每个项目的一些条件,如果满足这些条件,它会将项目及其状态存储在字典中。这本词典可以变得很大。

我尝试使用 CProfile 分析我的代码,我发现 garbage-collector 是使用了大约 90% 执行时间的函数。

我看到通过调用gc.disable() 解决了类似的问题,但这对我没有任何帮助。

很奇怪(我不知道这是否正常),但如果我将print(len(gc.get_objects())) 作为代码的第一行,我会得到51053,考虑到尚未调用任何函数,这似乎很多。

我的CProfile 尝试:(在一小部分 CSV 上,因为完成完整 CSV 上的尝试需要几个小时)

cProfile.run('get_pfs_errors("Logs/L5/L5_2000.csv")', 'restats.txt')


import pstats
from pstats import SortKey
p = pstats.Stats('restats.txt')
p.sort_stats(SortKey.CUMULATIVE).print_stats(10)
p.sort_stats(SortKey.TIME).print_stats(10)

这是来自CProfile 的统计数据:

Tue Jun 18 15:40:19 2019    restats.txt

         1719320 function calls (1459451 primitive calls) in 7.569 seconds

   Ordered by: cumulative time
   List reduced from 819 to 10 due to restriction <10>

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000    7.569    7.569 built-in method builtins.exec
        1    0.001    0.001    7.569    7.569 <string>:1(<module>)
        1    0.000    0.000    7.568    7.568 C:/Users/BC744818/Documents/OPTISS_L1_5/test_profile.py:6(get_pfs_errors)
        1    0.006    0.006    7.503    7.503 C:\Users\BC744818\Documents\OPTISS_L1_5\utils\compute_pfs_rules.py:416(compute_pfs_rules)
        1    0.197    0.197    7.498    7.498 C:\Users\BC744818\Documents\OPTISS_L1_5\utils\compute_pfs_rules.py:323(test_logs)
      264    0.001    0.000    6.532    0.025 C:\Users\BC744818\Documents\OPTISS_L1_5\venv\lib\site-packages\pandas\core\series.py:982(__setitem__)
      529    0.010    0.000    6.158    0.012 C:\Users\BC744818\Documents\OPTISS_L1_5\venv\lib\site-packages\pandas\core\generic.py:3205(_check_setitem_copy)
      528    6.125    0.012    6.125    0.012 built-in method gc.collect
      264    0.004    0.000    3.430    0.013 C:\Users\BC744818\Documents\OPTISS_L1_5\venv\lib\site-packages\pandas\core\series.py:985(setitem)
      264    0.004    0.000    3.413    0.013 C:\Users\BC744818\Documents\OPTISS_L1_5\venv\lib\site-packages\pandas\core\indexing.py:183(__setitem__)


Tue Jun 18 15:40:19 2019    restats.txt

         1719320 function calls (1459451 primitive calls) in 7.569 seconds

   Ordered by: internal time
   List reduced from 819 to 10 due to restriction <10>

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
      528    6.125    0.012    6.125    0.012 built-in method gc.collect
      264    0.405    0.002    0.405    0.002 built-in method gc.get_objects
        1    0.197    0.197    7.498    7.498 C:\Users\BC744818\Documents\OPTISS_L1_5\utils\compute_pfs_rules.py:323(test_logs)
 71280/33    0.048    0.000    0.091    0.003 C:\Users\BC744818\AppData\Local\Programs\Python\Python37\lib\copy.py:132(deepcopy)
   159671    0.033    0.000    0.056    0.000 built-in method builtins.isinstance
      289    0.026    0.000    0.026    0.000 built-in method nt.stat
167191/83791    0.024    0.000    0.040    0.000 C:\Users\BC744818\AppData\Local\Programs\Python\Python37\lib\json\encoder.py:333(_iterencode_dict)
  8118/33    0.019    0.000    0.090    0.003 C:\Users\BC744818\AppData\Local\Programs\Python\Python37\lib\copy.py:236(_deepcopy_dict)
167263/83794    0.017    0.000    0.048    0.000 C:\Users\BC744818\AppData\Local\Programs\Python\Python37\lib\json\encoder.py:277(_iterencode_list)
 1067/800    0.017    0.000    0.111    0.000 C:\Users\BC744818\Documents\OPTISS_L1_5\venv\lib\site-packages\pandas\core\indexes\base.py:253(__new__)

【问题讨论】:

我在处理大型DataFrame时遇到了类似的问题,禁用garbage-collector也没用。如果我没记错的话,问题是循环引用。我设法通过改变处理 DataFrame 的方式解决了这个问题。您能否提供有关您在 DataFrame 上执行的此循环的一些详细信息? 【参考方案1】:

谢谢@user9993950,多亏了你我解决了。

当我测试这个程序时,我有一个SettingWithCopyWarning,但我想在修复这个警告之前修复程序的速度。

然而,通过修复警告,我也大大提高了程序的速度,gc 不再占用所有运行时间

我不知道是什么原因造成的,如果有人知道并想分享知识,请这样做。

【讨论】:

以上是关于Python - 垃圾收集非常慢,无法禁用 gc的主要内容,如果未能解决你的问题,请参考以下文章

基于PHP Memcache(d)的会话:是否应禁用垃圾收集?

标记为垃圾收集vs符合java中的垃圾收集条件

什么时候在python中收集垃圾?

关闭D垃圾收集器

G1 GC垃圾收集流程

JVM优化 垃圾回收 算法 垃圾收集器 GC日志可视化查看