Linux下多进程Python代码内存总占用量计算难题
准确统计Linux下Python多进程(fork)的内存占用
你遇到的问题本质是Linux **Copy-On-Write(写时复制)**机制导致的:父进程fork子进程后,两者会共享父进程的大部分内存页(只要这些页没被修改),但每个进程的RSS(驻留集大小)会把这些共享页全部计入自己的统计,直接加总所有进程的RSS就会重复计算共享内存,导致结果远大于实际物理内存占用。
方法1:使用PSS(比例驻留集大小)统计
PSS是Linux提供的内存统计指标,它会把共享内存按共享该内存的进程数量平均分摊到每个进程上。所有进程的PSS值相加,就是程序实际占用的物理内存总量,完美解决重复统计问题。
用psutil可以直接获取进程的PSS值,修改你的print_mem_usage函数:
def print_mem_usage(): # 获取父进程PSS parent_pss = psutil.Process().memory_full_info().pss / 1000 # 获取子进程PSS child_pss = psutil.Process(process.pid).memory_full_info().pss / 1000 total_pss = parent_pss + child_pss print(f"Parent PSS: {parent_pss:.2f} KB, Child PSS: {child_pss:.2f} KB, Total PSS: {total_pss:.2f} KB")
这个总PSS值会和htop显示的实际内存占用基本一致,因为htop默认显示的就是类似PSS的聚合统计。
方法2:区分私有内存与共享内存
如果需要更细粒度的统计,可以拆分内存为私有内存(仅当前进程使用,不会被共享)和共享内存(多个进程共享,只需统计一次):
- 私有内存:
private_clean+private_dirty(psutil的memory_full_info()可以获取) - 共享内存:
shared_clean+shared_dirty
总内存计算方式:父进程私有内存 + 子进程私有内存 + 共享内存(取任意进程的共享值即可,因为共享部分是同一个)
修改示例函数:
def print_mem_usage(): parent_mem = psutil.Process().memory_full_info() child_mem = psutil.Process(process.pid).memory_full_info() parent_private = (parent_mem.private_clean + parent_mem.private_dirty) / 1000 child_private = (child_mem.private_clean + child_mem.private_dirty) / 1000 shared = (parent_mem.shared_clean + parent_mem.shared_dirty) / 1000 total = parent_private + child_private + shared print(f"Parent Private: {parent_private:.2f} KB, Child Private: {child_private:.2f} KB, Shared: {shared:.2f} KB, Total: {total:.2f} KB")
这种方式能清晰看到共享内存和私有内存的占比,适合排查内存问题。
为什么你的示例中子进程RSS接近父进程?
你的代码里父进程提前创建了large_arr这个大列表,fork子进程后,子进程并没有修改这个列表(只是遍历读取),所以这部分内存页完全由父子进程共享。子进程的RSS包含了这部分共享页,所以看起来和父进程RSS差不多,但实际子进程只占用了少量私有内存(比如small_local_arr和栈内存)。
内容的提问来源于stack exchange,提问作者Amir
相关产品推荐
相关产品推荐

