2025-11-30 · garbage-collection
【Garbage Collection Series】GC 横向对比:Java vs Go vs Python vs Rust
多维度对比主流编程语言的内存管理策略,分析吞吐量、延迟与开发效率的权衡。
Python (CPython) 的内存管理策略与 Java 和 Go 有显著不同。它主要依赖引用计数 (Reference Counting) 来进行内存回收,辅以一个分代循环垃圾收集器 (Generational Cyclic GC) 来解决引用循环问题。
这是 Python 内存管理的基石。每个 Python 对象都有一个
ob_refcnt 字段。
ob_refcnt
加 1。del、从容器移除时,ob_refcnt 减
1。ob_refcnt 降为 0
时,立即调用对象的析构函数 (__del__)
并释放内存。伪代码 (C 语言风格):
#define Py_INCREF(op) (op->ob_refcnt++)
#define Py_DECREF(op) \
if (--(op->ob_refcnt) == 0) \
_Py_Dealloc(op)为了解决 A -> B -> A
这种循环引用导致内存无法释放的问题,Python 引入了分代循环
GC。
只有可能包含引用的对象(如 list, dict, class, tuple)才会被 GC 跟踪。简单的原子类型(如 int, str)不需要 GC 跟踪,因为它们不可能构成环。
Python 使用一种基于引用计数副本的算法来检测环。
算法步骤 (伪代码):
def collect(generation):
# 1. 建立引用计数副本
# gc_refs = ob_refcnt
update_gc_refs()
# 2. 减去内部引用
# 遍历该代中所有对象,将其引用的对象的 gc_refs 减 1
# 这一步是为了消除"环"内部的引用影响
subtract_refs()
# 3. 标记可达对象
# 此时,如果 gc_refs > 0,说明有外部引用指向它,它是活跃的。
# 将其标记为 reachable,并递归标记其引用的对象。
move_unreachable_to_garbage()
# 4. 回收垃圾
# 剩下的 gc_refs == 0 的对象就是不可达的环
delete_garbage()Python 将对象分为三代:0 代、1 代、2 代。 * 0 代: 新创建的对象。 * 1 代: 幸存过一次 0 代回收的对象。 * 2 代: 幸存过一次 1 代回收的对象。
触发机制: * 当 0 代对象数量减去回收数量达到阈值(默认 700),触发 0 代 GC。 * 当 0 代 GC 发生一定次数(默认 10 次),触发 1 代 GC。 * 以此类推。
Python 提供了 gc 模块来控制垃圾回收。
gc.disable(): 关闭自动
GC(引用计数仍在工作)。在对性能要求极高且确信无循环引用的场景下使用。gc.collect(): 手动触发 Full GC。gc.set_threshold(): 调整分代阈值。Python 的 GC 是 引用计数 (主) + 分代循环 GC (辅)。 * 引用计数保证了大多数对象的实时回收。 * 分代 GC 兜底解决循环引用,避免内存泄漏。
把当前热点继续串成多页阅读,而不是停在单篇消费。
2025-11-30 · garbage-collection
多维度对比主流编程语言的内存管理策略,分析吞吐量、延迟与开发效率的权衡。
2025-11-30 · garbage-collection
深入分析 Go 语言的低延迟垃圾回收机制,包括三色标记法、混合写屏障以及 GC Pacing 调优。
2025-11-30 · garbage-collection
深入解析 Java 虚拟机 (JVM) 的垃圾回收算法,包括分代收集理论、CMS、G1 以及新一代的 ZGC 和 Shenandoah。
2025-11-30 · garbage-collection
探索垃圾回收技术的最新进展,包括 ZGC 的染色指针、读屏障技术以及 AI 驱动的参数调优。
Python (CPython) 的内存管理策略与 Java 和 Go 有显著不同。它主要依赖引用计数 (Reference Counting) 来进行内存回收,辅以一个分代循环垃圾收集器 (Generational Cyclic GC) 来解决引用循环问题。
这是 Python 内存管理的基石。每个 Python 对象都有一个
ob_refcnt 字段。
ob_refcnt
加 1。del、从容器移除时,ob_refcnt 减
1。ob_refcnt 降为 0
时,立即调用对象的析构函数 (__del__)
并释放内存。伪代码 (C 语言风格):
#define Py_INCREF(op) (op->ob_refcnt++)
#define Py_DECREF(op) \
if (--(op->ob_refcnt) == 0) \
_Py_Dealloc(op)为了解决 A -> B -> A
这种循环引用导致内存无法释放的问题,Python 引入了分代循环
GC。
只有可能包含引用的对象(如 list, dict, class, tuple)才会被 GC 跟踪。简单的原子类型(如 int, str)不需要 GC 跟踪,因为它们不可能构成环。
Python 使用一种基于引用计数副本的算法来检测环。
算法步骤 (伪代码):
def collect(generation):
# 1. 建立引用计数副本
# gc_refs = ob_refcnt
update_gc_refs()
# 2. 减去内部引用
# 遍历该代中所有对象,将其引用的对象的 gc_refs 减 1
# 这一步是为了消除"环"内部的引用影响
subtract_refs()
# 3. 标记可达对象
# 此时,如果 gc_refs > 0,说明有外部引用指向它,它是活跃的。
# 将其标记为 reachable,并递归标记其引用的对象。
move_unreachable_to_garbage()
# 4. 回收垃圾
# 剩下的 gc_refs == 0 的对象就是不可达的环
delete_garbage()Python 将对象分为三代:0 代、1 代、2 代。 * 0 代: 新创建的对象。 * 1 代: 幸存过一次 0 代回收的对象。 * 2 代: 幸存过一次 1 代回收的对象。
触发机制: * 当 0 代对象数量减去回收数量达到阈值(默认 700),触发 0 代 GC。 * 当 0 代 GC 发生一定次数(默认 10 次),触发 1 代 GC。 * 以此类推。
Python 提供了 gc 模块来控制垃圾回收。
gc.disable(): 关闭自动
GC(引用计数仍在工作)。在对性能要求极高且确信无循环引用的场景下使用。gc.collect(): 手动触发 Full GC。gc.set_threshold(): 调整分代阈值。Python 的 GC 是 引用计数 (主) + 分代循环 GC (辅)。 * 引用计数保证了大多数对象的实时回收。 * 分代 GC 兜底解决循环引用,避免内存泄漏。
把当前热点继续串成多页阅读,而不是停在单篇消费。
2025-11-30 · garbage-collection
多维度对比主流编程语言的内存管理策略,分析吞吐量、延迟与开发效率的权衡。
2025-11-30 · garbage-collection
深入分析 Go 语言的低延迟垃圾回收机制,包括三色标记法、混合写屏障以及 GC Pacing 调优。
2025-11-30 · garbage-collection
深入解析 Java 虚拟机 (JVM) 的垃圾回收算法,包括分代收集理论、CMS、G1 以及新一代的 ZGC 和 Shenandoah。
2025-11-30 · garbage-collection
探索垃圾回收技术的最新进展,包括 ZGC 的染色指针、读屏障技术以及 AI 驱动的参数调优。