python-3.x - 了解 Cpython 垃圾收集生成
问题描述
我正在努力提高对 python 中内存管理如何工作的理解,但我对 python 垃圾收集器模块中的世代概念感到困惑。
我的理解如下:
所有创建的对象都从第 0 代开始,一旦达到阈值(第 0 代默认为 700),python 将在该代运行一个集合,并且任何幸存的对象都会老化到下一代。
鉴于上述情况,我无法理解以下输出。
import gc
import sys
x = 1
print(gc.get_count())
gc.collect()
print(gc.get_count())
输出
(64, 1, 1)
(0, 0, 0)
首先,我只运行了 1 行代码,并且我已经在 gen 1 和 2 中获得了对象,这意味着垃圾收集已经发生了至少两次,这怎么可能?无论如何要找出每一代中的对象是什么?其次,为什么我在收集后的所有世代中都有 0 引用?我仍然可以运行命令print(x)
并且不会出错。这是否意味着仍然存在对 x 的引用,因此它应该存在于某一代中?
解决方案
gc.get_count()
向您显示每一代的计数器,朝向阈值。
不是每一代中对象的数量,而是计数器,当它到达线程持有时,该代的收集将发生。
例如,如果我从(0,0,0)
计数器开始,运行x = [[] for i in range(100)]
会将计数器设置为(101,0,0)
.
运行y = [[] for i in range(600)]
将导致计数器翻转(0,1,0)
并gen0
运行收集。在这一点上,我的所有列表都将移至gen1
它们在gen0
收藏中幸存下来。
当计数器到达(699,699,0)
并分配另一个对象时,gen0
将gen1
发生收集并且计数器将转到(0,0,1)
. 当 counter 达到(699,699,699)
,并且分配了一个对象,或者您使用gc.collect()
(运行gen2
集合)时, counter 将重置回(0,0,0)
.
要获取每一代中的对象,请使用gc.get_objects(gen)
.
关于代码运行之前的垃圾收集 - 当 Python 启动时,它会在加载脚本之前创建大量对象。例如,您可以看到通过运行加载的模块sys.modules
。创建这些对象后,垃圾收集器会自动运行。
推荐阅读
- cakephp - CakePHP 路由不接收参数
- python - 如何在 python/pandas 中过滤大数据框中的联合数据?
- python - 将烧瓶应用程序部署到heroku服务器后出现找不到模块错误
- python - 尝试运行 docplex 示例时出现 BrokenProcessPool 错误
- html -
屏幕缩小后隐藏 - apache-spark - SparkLauncher 独立集群模式
- socket.io - NestJS + Socket.io:没有收到消息
- ruby-on-rails - 多态关联通过关注给未定义的方法relation_delegate_class
- c# - (UWP)System.Runtime.InteropServices.COMException: '错误 HRESULT E_FAIL 已从对 COM 组件的调用中返回。'
- python - Python 2.7 将列表写入 CSV 数据,一些数据是 unicode,一些数据是字符串。哪个更有效地输出到地理数据库中的 dbf 表?