python - 在Python中释放大对象

标签 python garbage-collection cpython

据我所知,CPython 垃圾收集仅适用于等于或小于 512 字节的对象。对于大型对象,CPython 使用系统调用。

import psutil
print(psutil.Process().memory_info().rss)
import gc


gc.disable()
x = [[0] * 1000 for _ in range(100000)]

print(psutil.Process().memory_info().rss)

x = 1

print(psutil.Process().memory_info().rss)

代码输出如下:

19038208

440745984

21344256

这里[[0] * 1000 for _ in range(100000)]是一个大对象,远大于512字节。所以它不应该被gc模块收集。所以我尝试注释掉 gc.disable() ,输出几乎保持不变。这意味着 gc 模块没有收集垃圾对象。

现在我的问题是,如果 gc 不收集大对象,内存利用率如何减少?如何识别该对象是垃圾并且应该被收集?垃圾对象是通过什么方式被收集的?这里的垃圾对象实际上可以在程序终止之前释放吗?

最佳答案

CPython 中的大多数垃圾收集都是通过引用计数来处理的。 gc模块只需要收集涉及引用循环的对象(引用计数无法检测到),但你发布的程序中没有这样的东西。所以 gc 是无关紧要的。

但是引用计数和循环垃圾回收都不知道对象的大小。一个物体要么是垃圾,要么不是。这就是他们关心的一切。它是对象的释放函数,负责回收内存。在您的程序中,“大”内存块很可能通过调用 C 的 free() 函数返回到系统 C malloc 系列。这是否会通过 psutil 减少内存使用,这不是由 Python 决定的,而是由平台 C 库与操​​作系统的交互方式决定的。

要回答你的最后一个问题,是的,你的大对象会变成垃圾,并且在 x = 1 执行后立即调用它的释放函数。因为一旦新对象1绑定(bind)到x(x持有唯一的引用),大对象的引用计数就会降为0大物体)。

关于python - 在Python中释放大对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59871880/

相关文章:

python - Python 字节码在 CPython 中究竟是如何运行的?

python - Python的代码对象是什么类型?

python - 用户定义类的默认哈希值是什么?

python - 鼠兔无法创建仲裁队列

python - 从文本 Python 中识别和提取日期的最佳方法?

python - 如何使用 numpy 有效地计算一个系列?

java - 非常大的堆大小,但使用的内存很小

c# - GC 是否需要多次收集具有挂起终结器的对象?

javascript - 如何使用 jQuery 执行服务器端 Python 脚本?

c# - 为什么 Roslyn 中有这么多对象池的实现?