土法炼钢兴趣小组的算法知识备份

GC 横向对比:Java vs Go vs Python vs Rust

目录

引言

不同的编程语言选择了不同的内存管理路线,这直接决定了它们的适用场景。本文将从算法原理、屏障技术、停顿模型等维度进行深度对比。

1. 核心特性对比表

特性 Java (G1/ZGC) Go (1.18+) Python (CPython) Rust
主要算法 分代 + 标记-整理/复制 并发三色标记-清除 引用计数 + 分代循环 GC 所有权 (编译期)
分代假设 强依赖 (Young/Old) 不分代 (弱分代优化) 依赖 (3代) N/A
整理 (Compaction) 是 (解决碎片) 否 (使用 TCMalloc 类似分配器) 否 (对象不可移动) N/A
屏障技术 写屏障 (SATB/Card), 读屏障 (ZGC) 混合写屏障 (Dijkstra + Yuasa) 无 (Ref Count 更新) N/A
循环引用处理 自动处理 (Tracing GC) 自动处理 (Tracing GC) 需分代 GC 扫描 Weak 引用或手动破环
STW 延迟 G1 (可控), ZGC (<1ms) 极低 (<1ms) 无 (Ref Count), 偶发 (GC)
吞吐量 高 (Parallel/G1) 中 (为延迟牺牲吞吐) 低 (解释器 + Ref Count 开销) 极高 (无运行时开销)

2. 深度分析

2.1 Java vs Go: 吞吐量与延迟的博弈

2.2 Python: 简单与代价

2.3 Rust: 第三条路

Rust 没有运行时 GC。它通过所有权 (Ownership)借用 (Borrowing) 规则,在编译期插入内存释放代码 (drop)。 * 优势: 既有 C++ 的性能(无 GC 开销),又有 Java/Go 的内存安全。 * 劣势: 学习曲线陡峭。开发者必须通过编译器的借用检查器 (Borrow Checker)。

3. 伪代码对比:内存分配

Java (TLAB Bump Pointer):

// 极快,仅需移动指针
if (top + size <= end) {
    obj = top;
    top += size;
    return obj;
}

Go (Size Class Allocation):

// 查找对应大小的 span
size_class = size_to_class(size)
span = mcache.alloc[size_class]
if span.has_free() {
    return span.pop()
}

Rust (Stack Allocation):

// 编译期确定,栈分配,零开销
let x = MyStruct { ... }; 

总结


By .