zoukankan      html  css  js  c++  java
  • python cProfile分析程序性能

    转自:http://xianglong.me/article/analysis-python-application-performance-using-cProfile/?utm_source=tuicool&utm_medium=referral

    Python标准库中提供了三种用来分析程序性能的模块,分别是cProfile, profile和hotshot,另外还有一个辅助模块stats。这些模块提供了对Python程序的确定性分析功能,同时也提供了相应的报表生成工具,方便用户快速地检查和分析结果。

        这三个性能分析模块的介绍如下:

        cProfile:基于lsprof的用C语言实现的扩展应用,运行开销比较合理,适合分析运行时间较长的程序,推荐使用这个模块;

        profile:纯Python实现的性能分析模块,接口和cProfile一致。但在分析程序时增加了很大的运行开销。不过,如果你想扩展profiler的功能,可以通过继承这个模块实现;

        hotshot:一个试验性的C模块,减少了性能分析时的运行开销,但是需要更长的数据后处理的次数。目前这个模块不再被维护,有可能在新版本中被弃用。

        由于hotshot基本不再使用,而profile和cProfile的用法基本一致,所以下面就只介绍一下cProfile的用法。

     一、cProfile基本用法 

        假设现在有这样一个Python函数,需要测试一下它的运行速度:

     1 def sum_num(max_num):
     2     total = 0
     3     for i in range(max_num):
     4         total += i
     5     return total
     6  
     7  
     8 def test():
     9     total = 0
    10     for i in range(40000):
    11         total += i
    12  
    13     t1 = sum_num(100000)
    14     t2 = sum_num(400000)
    15  
    16     return total
    17  
    18 if __name__ == "__main__":
    19     test()

    下面使用cProfile进行性能分析,你可以在Python脚本中实现,也可以使用命令行执行。使用Python脚本的主函数代码如下:

    1 if __name__ == "__main__":
    2     import cProfile
    3  
    4     # 直接把分析结果打印到控制台
    5     cProfile.run("test()")
    6     # 把分析结果保存到文件中
    7     cProfile.run("test()", filename="result.out")
    8     # 增加排序方式
    9     cProfile.run("test()", filename="result.out", sort="cumulative")

     使用命令行运行的方法基本一致,Bash代码如下:

    1 # 直接把分析结果打印到控制台
    2 python -m cProfile test.py
    3 # 把分析结果保存到文件中
    4 python -m cProfile -o result.out test.py
    5 # 增加排序方式
    6 python -m cProfile -o result.out -s cumulative test.py

     使用最后一种方式分析的运行结果如下:

             8 function calls in 0.042 seconds
     
       Ordered by: cumulative time
     
       ncalls  tottime  percall  cumtime  percall filename:lineno(function)
            1    0.000    0.000    0.042    0.042 test.py:5(<module>)
            1    0.002    0.002    0.042    0.042 test.py:12(test)
            2    0.035    0.018    0.039    0.020 test.py:5(sum_num)
            3    0.004    0.001    0.004    0.001 {range}
            1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}

    其中,输出每列的具体解释如下:

        ncalls:表示函数调用的次数;

        tottime:表示指定函数的总的运行时间,除掉函数中调用子函数的运行时间;

        percall:(第一个percall)等于 tottime/ncalls;

        cumtime:表示该函数及其所有子函数的调用运行的时间,即函数开始调用到返回的时间;

        percall:(第二个percall)即函数运行一次的平均时间,等于 cumtime/ncalls;

        filename:lineno(function):每个函数调用的具体信息;

        另外,上面分析的时候,排序方式使用的是函数调用时间(cumulative),除了这个还有一些其他允许的排序方式:calls, cumulative, file, line, module, name, nfl, pcalls, stdname, time等。具体的结果如何,大家可以试试。

        二、分析工具pstats

        使用cProfile分析的结果可以输出到指定的文件中,但是文件内容是以二进制的方式保存的,用文本编辑器打开时乱码。所以,Python提供了一个pstats模块,用来分析cProfile输出的文件内容。它支持多种形式的报表输出,是文本界面下一个较为实用的工具。使用非常简单:

     1 import pstats
     2  
     3 # 创建Stats对象
     4 p = pstats.Stats("result.out")
     5  
     6 # strip_dirs(): 去掉无关的路径信息
     7 # sort_stats(): 排序,支持的方式和上述的一致
     8 # print_stats(): 打印分析结果,可以指定打印前几行
     9  
    10 # 和直接运行cProfile.run("test()")的结果是一样的
    11 p.strip_dirs().sort_stats(-1).print_stats()
    12  
    13 # 按照函数名排序,只打印前3行函数的信息, 参数还可为小数,表示前百分之几的函数信息 
    14 p.strip_dirs().sort_stats("name").print_stats(3)
    15  
    16 # 按照运行时间和函数名进行排序
    17 p.strip_dirs().sort_stats("cumulative", "name").print_stats(0.5)
    18  
    19 # 如果想知道有哪些函数调用了sum_num
    20 p.print_callers(0.5, "sum_num")
    21  
    22 # 查看test()函数中调用了哪些函数
    23 p.print_callees("test")

    此外,pstats也提供了命令行交互工具,方法如下: 

     1 xianglong@xianglong:~$ python -m pstats result.out 
     2 Welcome to the profile statistics browser.
     3 result.out% sort cumulative
     4 result.out% stats
     5 Thu Feb  5 16:08:36 2015    result.out
     6  
     7          8 function calls in 0.042 seconds
     8  
     9    Ordered by: cumulative time
    10  
    11    ncalls  tottime  percall  cumtime  percall filename:lineno(function)
    12         1    0.000    0.000    0.042    0.042 test.py:5(<module>)
    13         1    0.002    0.002    0.042    0.042 test.py:12(test)
    14         2    0.036    0.018    0.040    0.020 test.py:5(sum_num)
    15         3    0.004    0.001    0.004    0.001 {range}
    16         1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}
    17  
    18 result.out% help
    19  
    20 Documented commands (type help <topic>):
    21 ========================================
    22 EOF  add  callees  callers  help  quit  read  reverse  sort  stats  strip
    23  
    24 result.out%

    三、图形化工具

        对于一些比较大的应用程序,如果能够将性能分析的结果以图形的方式呈现,将会非常实用和直观,常见的可视化工具有Gprof2Dot,visualpytune,KCacheGrind等,这里介绍一下Gprof2Dot的用法。

        使用之前,你需要安装graphviz:

    sudo apt-get install graphviz

      然后下载Gprof2Dot:gprof2dot.py

        之后运行:

    python gprof2dot.py -f pstats result.out | dot -Tpng -o result.png
  • 相关阅读:
    Lua笔记
    psp info
    防火墙选项变成灰色解决办法
    server error.分析器错误信息: 未能加载类型. line 1
    [C++][stl]vector、list、deque
    恢复隐藏文件ShowAll.reg
    C++笔记
    C#成员的继承
    C#运算符重载
    .NET每个开发人员现在应该下载的十种必备工具
  • 原文地址:https://www.cnblogs.com/guolei2570/p/8760814.html
Copyright © 2011-2022 走看看