• python profile 性能分析


    背景

    自己写了一个小型项目, 写完发现运行一次要好几秒, 瓶颈在哪呢? 有无优化空间?
    涉及到的对象比较多, 方法间的嵌套和递归调用也不少, 很难手工打印时间戳去分析耗时. 此时就需要专业工具啦.

    一. cProfile

    详见参考 [1].
    python sdk 内置的库, 可以统计程序各方法的执行频次耗时, 还能分别展现是否计入子调用(即嵌套调用)的性能指标.

    多线程

    好像感知不到其他线程的运行与性能.

    普通方法

    web应用内的方法

    @app.route('/hello', methods=['POST'])
    def hello():
        request_data_json = json.loads(request.data)
        feature_contrib_res_dict = ExplainServiceWrapper.brief_explain(copy.copy(request_data_json),
                                                                       feature_conf)
        http_response = make_response(feature_contrib_res_dict, 200)
        return http_response
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    现在想分析 ExplainServiceWrapper.brief_explain() 的性能, 比起普通方法, 有几处不便:

    1. 方法的入参来自 web请求, 本地 mock 方法实参不方便.
    2. cProfile.run(‘ExplainServiceWrapper.brief_explain’) 无法传参, 也无法得到返回值.
    3. server_app 线程是永久运行的, 即便 cProfile.run(app.run) 也无法正常返回

    解决办法, 使用 werkzeug 工具包提供的 wrapper 类: ProfilerMiddleware. 例子见下:

    from werkzeug.middleware.profiler import ProfilerMiddleware
    app = Flask(app_name)
    app = ProfilerMiddleware(app)
    # 其他照旧
    
    """
    PATH: '/hello'
             498099 function calls (490270 primitive calls) in 4.344 seconds
    
       Ordered by: internal time, call count
    
       ncalls  tottime  percall  cumtime  percall filename:lineno(function)
            2    4.057    2.029    4.057    2.029 {method 'recv_into' of '_socket.socket' objects}
            2    0.085    0.043    0.085    0.043 {method 'connect' of '_socket.socket' objects}
         1095    0.075    0.000    0.075    0.000 {method 'join' of 'str' objects}
            2    0.040    0.020    0.062    0.031 D:\ProgrammingFiles\Anaconda3\lib\urllib\parse.py:910()
       460304    0.022    0.000    0.022    0.000 {method '__getitem__' of 'dict' objects}
            2    0.019    0.009    0.019    0.009 {built-in method _socket.getaddrinfo}
          471    0.012    0.000    0.086    0.000 D:\code_work\if_interpretable_model\feature_utils.py:56(indicator_convert)
          470    0.007    0.000    0.007    0.000 {built-in method numpy.array}
            4    0.005    0.001    0.005    0.001 {method 'sendall' of '_socket.socket' objects}
            1    0.002    0.002    4.341    4.341 D:\code_work\if_interpretable_model\if_explainer\_if_brief_explainer.py:28(_explain)
    """
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    格式解读

    todo

    可视化

    flameprof

    1. pip install flameprof
    2. python -m flameprof “D:\code_work\if_se_torch\profile_stat.prof” > a.svg
      在这里插入图片描述

    参考

    1. python 官方 profile 文档
  • 相关阅读:
    【C++】GoogleTest入门指南
    解决SyntaxError: Cannot use import statement outside a module(ts文件运行问题)
    IP详细地理位置查询:技术原理与应用实践
    人工智能(AI)基础知识学习库
    Redis配置与优化
    gpg: keyserver receive failed: Cannot assign requested address
    使用JLINK给GD32下载程序
    【1】Docker安装
    [Linux]进程信号(信号入门 | 信号产生的方式 | 信号捕捉初识)
    《C 陷阱与缺陷 》阅读概要
  • 原文地址:https://blog.csdn.net/chuchus/article/details/128020116