You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Python读取文件后删除数据,内存占用无法恢复至初始状态的原因及API服务内存增长疑问

Python读取文件后删除数据,内存占用无法恢复至初始状态的原因及API服务内存增长疑问

嗨,我完全理解你看到内存没回到初始值时的困惑——按直觉删了数据内存就该降回去才对,其实这种情况是Python内存管理的正常表现,咱们一步步拆解原因,再说说API服务的内存顾虑:

一、为什么删除数据后内存没法回到初始值?

  1. Python的内存池机制
    Python自带专属的内存分配器(比如小对象用pymalloc),它不会把释放的内存立刻还给操作系统。当你del data并调用gc.collect()后,这些内存会被Python存在自己的内存池里,留着给后续的内存分配复用。而你用rss统计的是进程实际占用的物理内存,操作系统还没收回这部分内存,所以数值不会立刻降到初始状态。

  2. JSON解析的额外残留开销
    json.loads()处理大文件时,除了生成data对象,还会产生一些临时对象、字符串缓存(比如Python的字符串intern机制会缓存重复的短字符串,避免重复创建),或者解释器内部的临时结构。虽然del data删掉了核心对象,但这些零散的小内存块可能没法被彻底回收,或者gc清理起来有延迟,也会让内存有少量残留。

另外,你原来的代码里没显式删除c这个读取文件得到的大字符串——它也占了不少内存!虽然gc最终可能会处理,但显式del c能更快释放这部分空间。

  1. RSS统计的局限性
    初始的11.875MB是程序刚启动的状态:这时候很多模块(比如psutiljson)还没完全加载,解释器内部的缓存也没建立。当你运行过一次读取解析后,模块已经加载完成,解释器的内部状态也变了,这些开销是永久的(只要程序在运行),所以哪怕回收了所有业务数据,内存也不可能回到刚启动时的水平。

二、API服务会不会一直无限增长内存?

放心,只要你的代码没有内存泄漏(比如意外保留了对大对象的引用,比如把处理完的data存在全局变量、闭包、或者某个没清理的缓存里),内存不会无限增长。

Python的内存池会复用之前释放的内存:当新的请求进来时,会优先从内存池里分配空间,而不是向操作系统申请新内存。只有当请求需要的内存超过了当前内存池的大小,rss才会临时增长,但后续的请求会复用之前释放的空间,内存最终会稳定在一个合理的范围。

你可以做个简单测试:把读取-删除的逻辑循环跑个5-10次,看看内存是不是稳定在某个值,而不是每次循环都涨。比如修改你的代码:

import psutil
import os
import json
import gc

def main():
    pid = os.getpid()
    print(f"pid of program is {pid}")
    
    # 初始内存
    memory_info = psutil.Process(pid).memory_info()
    print(f'initial memory: {memory_info.rss / (1024 * 1024):.2f} MB')
    
    # 循环多次测试
    for i in range(5):
        with open('temp.json', 'r') as file:
            c = file.read()
            data = json.loads(c)
        
        memory_info = psutil.Process(pid).memory_info()
        print(f'after read {i+1}: {memory_info.rss / (1024 * 1024):.2f} MB')
        
        # 显式删除所有大对象
        del data
        del c
        gc.collect()
        
        memory_info = psutil.Process(pid).memory_info()
        print(f'after delete {i+1}: {memory_info.rss / (1024 * 1024):.2f} MB')
        print("---")

if __name__ == "__main__":
    main()

运行后你会发现,第一次循环后内存会涨,但后面几次循环的内存波动会很小,最终稳定在一个值,不会持续上升。

总结一下

  • 内存没回到初始值是Python内存管理的正常设计,不是内存泄漏;
  • 正常的API服务只要没有泄漏,内存会稳定在一个区间,不会无限增长;
  • 如果实在担心,可以用tracemalloc模块跟踪内存分配,排查有没有意外的引用保留。

备注:内容来源于stack exchange,提问作者Saksham Ghimire

火山引擎 最新活动