You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python内存管理疑问:pybind11与原生对象内存释放差异原因

关于pybind11封装对象与Python原生对象删除后内存回收差异的疑问

我发现删除pybind11封装的对象时,内存不会归还操作系统,而是留存于内存池中;但删除Python原生对象时,内存会直接归还给系统。我通过以下测试代码验证了该现象,特向大家询问造成这一差异的原因。因某些原因无法展示完整代码,故使用伪代码说明:

pybind11测试代码

def observe_mem_func():
    print('Memory already in use:',
          psutil.Process(os.getpid()).memory_info().rss // 1024 // 1024 // 1024)

# 初始化pybind11对象前显示系统已用内存
observe_mem_func()
# init_pybind_object函数会返回两个pybind11封装的对象
pybind_object_1, pybind_object_2 = init_pybind_object()
# 初始化pybind11对象后显示系统已用内存
observe_mem_func()

# 删除pybind11对象
del pybind_object_1
del pybind_object_2
gc.collect()
# 删除pybind11对象后显示系统已用内存
observe_mem_func()

# 再次初始化对象,可见内存从内存池中获取,说明内存未归还系统
pybind_object_3, pybind_object_4 = init_pybind_object()
observe_mem_func()

运行结果(单位:G)

Memory already in use: 0
Memory already in use: 1
Memory already in use: 1
Memory already in use: 1

Python原生对象测试代码

def observe_mem_func():
    print('Memory already in use:',
          psutil.Process(os.getpid()).memory_info().rss // 1024 // 1024 )

class Base:
    def __init__(self, str) -> None:
        self.str = str

def init_base():
    with open("test_code/file.txt", 'r') as fp:
        return Base(fp.read())

a = []
print("Init Base object")
for i in range(5):
    a.append(init_base())
    observe_mem_func()

print("Del object")
for i in range(5):
    a.pop()
    observe_mem_func()

运行结果(单位:M)

Init Base object
Memory already in use: 215
Memory already in use: 246
Memory already in use: 277
Memory already in use: 307
Memory already in use: 338
Del object
Memory already in use: 307
Memory already in use: 277
Memory already in use: 246
Memory already in use: 215
Memory already in use: 185


差异原因分析

  • 内存分配器不同
    Python原生对象使用解释器自带的pymalloc分配器,针对大对象(如测试中读取大文件的字符串),pymalloc会在对象回收后将内存归还给操作系统;而pybind11封装的C对象由C默认分配器(malloc/new)分配,这类分配器会把释放的内存留在内部内存池,用于后续快速分配,不会立即归还系统。
  • 内存管理控制权差异
    Python原生对象的内存完全由解释器掌控,可根据自身策略决定是否归还内存;pybind11对象的底层内存由C运行时管理,Python仅能触发对象析构,无法干预C分配器的内存池行为。
  • 测试场景的印证
    pybind11测试中再次创建对象时内存未增长,说明内存池复用了之前释放的内存;Python原生测试中内存随对象删除逐步下降,是因为大对象使用系统分配器,释放时直接归还操作系统。

内容的提问来源于stack exchange,提问作者Dylan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 14:44:59