Python 内存管理机制与垃圾回收机制
对 CPython 的内存管理机制与垃圾回收机制简单的总结。
Python 内存管理机制
下面是一张 CPython 的内存架构图:
Python 的对象管理主要位于 Level +3 至 Level +1 层。从上往下看:
- 对于 int, dict, list 等 Python 内置的对象,都有独立的私有内存池,对象之间内存池不共享,即 string 释放的内存不会给 int 类型使用。对于内置类型,有单独的分配器。
- 对于小于等于 512 Bytes的对象,使用 Pymalloc 在内存池中分配。内存池大小为 64MB?把内存池抽象为三种结构
arena
,pool
和block
。arena
大小是固定的,默认为256KB。一个arena
含有多个pool
(大小为 4KB?),一个pool
含有多个block
。- 内存池机制:当创建大量消耗小内存的对象时,频繁调用 new/malloc 会导致大量的内存碎片,使效率降低。内存池的概念就是预先在内存中申请一定数量的,大小相等的内存块留作备用,当有新的内存需求时,就先从内存池中分配内存给这个需求,不够了之后再申请新的内存。这样做最显著的优势就是能够减少内存碎片,提升效率。
- 对于大于 512 Bytes的对象,会使用
PyMem_RawMalloc()
和PyMem_RawRealloc()
来申请新的内存空间。本质是使用 C 的 malloc 和 realloc 函数。
内存中存在堆空间与栈空间两个区域。堆空间存储的是对象,栈空间存储的是对象在栈空间的地址。
Python 垃圾回收机制
Python 的垃圾回收机制以引用记数为主,分代回收为辅。为了解决引用计数无法解决的循环引用问题,使用了一种标记清除方法识别循环引用。
首先,会触发垃圾回收的行为有:
- 手动调用
gc.collect()
- 当
gc
模块的计数器达到阈值的时候 - 程序退出的时候
接下来,了解相关概念。
-
引用记数。
-
Python 中一切皆对象,每个对象中都含有引用记数
ob_refcnt
。可以用过sys
模块中的getrefcount(obj)
方法获取 obj 的引用计数。x = object() print(sys.getrefcount(x)) # 2 y = x print(sys.getrefcount(x)) # 3 d
-