垃圾回收代码解析
这段代码展示了 Python 中 gc 模块的使用,用于手动控制和监视垃圾回收机制。
代码结构
import gc
gc.get_threshold()
gc.collect()
逐行分析
第1行:import gc
- 导入 Python 的垃圾回收模块
- gc 模块提供了与循环垃圾回收器交互的接口
第2行:gc.get_threshold()
- 获取当前 GC 的阈值设置
- 返回一个三元组:(threshold0, threshold1, threshold2)
第3行:gc.collect()
- 手动触发一次完整的垃圾回收
- 返回回收的对象数量
GC 阈值详解
thresholds = gc.get_threshold()
# 返回: (700, 10, 10)
含义:
threshold0 (700) – 第0代阈值:新对象分配数量达到 700 时触发 GC
threshold1 (10) – 第1代阈值:第0代回收次数达到 10 次时,检查第1代
threshold2 (10) – 第2代阈值:第1代回收次数达到 10 次时,检查第2代
分代回收机制
对象生命周期流程:
┌─────────────┐
│ 新对象创建 │ → 进入第0代(Generation 0)
└──────┬──────┘
│ 分配计数器累加
↓ 当计数器 > threshold0
┌─────────────┐
│ 触发 GC │ → 扫描第0代,回收不可达对象
└──────┬──────┘
│ 存活对象 → 进入第1代
↓ 回收次数累加
┌─────────────┐
│ 第1代 GC │ → 当计数器 > threshold1
└──────┬──────┘
│ 存活对象 → 进入第2代
↓
┌─────────────┐
│ 第2代 GC │ → 当计数器 > threshold2
└─────────────┘
gc.collect() 详解
collected = gc.collect()
# 返回: 回收的对象数量
print(f"回收了 {collected} 个对象")
完整示例
import gc
import sys
# 查看当前阈值
thresholds = gc.get_threshold()
print(f"GC 阈值: {thresholds}")
# 输出: GC 阈值: (700, 10, 10)
# 查看当前各代对象数量
print(f"第0代: {gc.get_count()[0]}")
print(f"第1代: {gc.get_count()[1]}")
print(f"第2代: {gc.get_count()[2]}")
# 创建一些对象
data = []
for i in range(100):
data.append({'value': i})
# 手动触发 GC
collected = gc.collect()
print(f"回收对象数: {collected}")
调整 GC 阈值
import gc
# 设置新阈值
gc.set_threshold(1000, 15, 15)
# 减少垃圾回收频率(适用于内存充足的应用)
gc.set_threshold(2000, 20, 20)
# 增加垃圾回收频率(适用于内存受限的环境)
gc.set_threshold(400, 5, 5)
实际应用场景
1. 内存密集型应用
import gc
def process_large_data():
data = load_large_dataset()
result = process(data)
del data # 删除引用
# 立即释放内存
gc.collect()
return result
2. 性能测试
import gc
import time
def benchmark():
# 禁用 GC 进行测试
gc.disable()
start = time.time()
# 执行测试代码…
elapsed = time.time() – start
# 重新启用 GC
gc.enable()
gc.collect()
return elapsed
3. 调试循环引用
import gc
# 启用调试标志
gc.set_debug(gc.DEBUG_SAVEALL)
# 运行代码…
# 检查未回收的对象
print(gc.garbage) # 查看无法回收的对象
循环引用示例
import gc
class A:
def __del__(self):
print("A deleted")
class B:
def __del__(self):
print("B deleted")
# 创建循环引用
a = A()
b = B()
a.ref = b # a 引用 b
b.ref = a # b 引用 a
# 删除外部引用
del a
del b
# 引用计数为0,但对象间仍相互引用
# 手动触发 GC 处理循环引用
collected = gc.collect()
print(f"回收了 {collected} 个对象")
# 输出:
# A deleted
# B deleted
# 回收了 2 个对象
GC 统计信息
import gc
# 获取 GC 统计信息
stats = gc.get_stats()
for i, gen_stat in enumerate(stats):
print(f"第{i}代统计:")
print(f" 回收次数: {gen_stat['collections']}")
print(f" 回收对象: {gen_stat['collected']}")
print(f" 未回收对象: {gen_stat['uncollectable']}")
关键设计决策
1. 自动 vs 手动
- Python 默认自动进行垃圾回收
- gc.collect() 用于手动控制,适用于特定场景
2. 性能 vs 内存
- 较低的阈值:更频繁回收,内存占用低,但性能略降
- 较高的阈值:较少回收,性能提升,但内存占用高
3. 循环引用处理
- 引用计数无法处理循环引用
- GC 使用标记-清除算法处理循环引用
最佳实践
1. 内存敏感应用
# 在关键时刻强制回收
gc.collect()
2. 性能关键代码
# 临时禁用 GC
gc.disable()
try:
# 执行性能关键代码
perform_critical_task()
finally:
gc.enable()
gc.collect()
3. 调试内存泄漏
# 记录 GC 前后的对象数量
before = len(gc.get_objects())
# 执行代码…
after = len(gc.get_objects())
print(f"新增对象: {after – before}")
学习要点
这是 Python 内存管理的核心机制,理解 GC 对于编写高性能、低内存占用的应用至关重要。



