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

Python3.7.9下循环/Flask中pyinstrument内存持续增长问题求解

解决pyinstrument在循环/Flask中内存持续增长的问题

问题背景

Python版本为3.7.9,使用pyinstrument时出现内存泄漏情况:

测试循环场景代码:

from pyinstrument import Profiler
import gc

def a():
    profiler = Profiler()
    profiler.start()
    a=1+1
    b=a+2
    profiler.stop()
    profiler.output_text(unicode=True, color=False, show_all=False, )
    profiler.reset()
    profiler = None
    del profiler
    gc.collect()


if __name__ == '__main__':
    for i in range(100000000):
        a()
    pass

循环中使用pyinstrument内存持续增长,移除del profiler和gc.collect()后增长速度会大幅加快。

实际Flask场景代码:

@app.before_request
def start_timer():
    g.profiler = Profiler()
    g.profiler.start()
    request.start_time = time.time()


@app.after_request
def log_request(response):
    total_time = time.time() - request.start_time
    logging.info(f"{total_time :.2f}")
    g.profiler.stop()
    if total_time > 10:
        logging.info(g.profiler.output_text(unicode=True, color=False, show_all=False, ))
    g.profiler.reset()
    g.profiler = None
    return response

同样存在内存持续增长的问题,需彻底解决。

解决方案

  • 升级pyinstrument版本
    pyinstrument旧版本存在已知的内存泄漏问题,尤其在频繁创建销毁Profiler实例的场景下。升级到最新稳定版,新版本针对这类场景做了内存优化,能有效缓解泄漏问题。

  • 复用Profiler实例
    避免每次请求或循环都新建Profiler对象,改为创建全局复用实例,每次使用后重置即可:
    Flask场景修改示例:

    # 初始化全局Profiler实例
    profiler = Profiler()
    
    @app.before_request
    def start_timer():
        profiler.reset()  # 重置之前的记录
        profiler.start()
        request.start_time = time.time()
    
    
    @app.after_request
    def log_request(response):
        total_time = time.time() - request.start_time
        logging.info(f"{total_time :.2f}")
        profiler.stop()
        if total_time > 10:
            logging.info(profiler.output_text(unicode=True, color=False, show_all=False))
        return response
    

    这种方式避免了频繁创建销毁对象带来的内存开销,同时降低GC压力。

  • 补充资源清理操作
    部分场景下reset()方法可能未完全清理内部跟踪数据,可在重置后触发轻量GC:

    import gc
    profiler.reset()
    gc.collect(1)  # 仅回收新生代对象,开销较小
    
  • 替换为轻量级计时方案
    如果仅需统计任务耗时,不需要完整的调用栈分析,直接用time模块替代pyinstrument,完全避免内存问题:

    @app.before_request
    def start_timer():
        request.start_time = time.time()
    
    
    @app.after_request
    def log_request(response):
        total_time = time.time() - request.start_time
        logging.info(f"{total_time :.2f}")
        if total_time > 10:
            logging.info(f"请求耗时过长: {total_time:.2f}s")
        return response
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 16:27:25