据我所知,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/