如何进行python性能分析?

在分析python代码性能瓶颈,但又不想修改源代码的时候,ipython shell以及第三方库提供了很多扩展工具,可以不用在代码里面加上统计性能的装饰器,也能很方便直观的分析代码性能。下面以我自己实现的一个快排代码为例,带你使用集中不同的性能分析工具。

def quick_sort(data, low, high):
    if low >= high:
        return
    
    left, right = low, high
    key = data[left]
    while left < right:
        while left < right and data[right] >= key:
            right -= 1
        data[left] = data[right]
        while left < right and data[left] <= key:
            left += 1
        data[right] = data[left]
    
    data[right] = key
    quick_sort(data, low, left - 1)
    quick_sort(data, left + 1, high)
    
import random
data = [random.randint(0, 1000) for _ in xrange(500)]

time

在ipython shell中,通过输入命令%time quick_sort(data, 0, 499)就可以查看调用耗时。

其中time命令的输出wall time是实际耗时的意思,通过简单的耗时查看就可以得出此快排算法针对不均匀分布的数组要慢很多。

timeit

在ipython shell中,通过输入命令%timeit -n 100 -r 5 quick_sort(data, 0, 499),就可以很方便的实现多次调用找到最短耗时。

此命令的含义就是重复100遍,每遍调用5此quick_sort,timeit会返回每遍的最短平均耗时。

line_profiler

line_profiler可以分析函数内每一行的执行时间,可以很方便的找出性能瓶颈。line_profiler不是ipython自带工具,需要通过pip install line_profiler安装。在ipython交互界面,通过下面方式使用:

首先需要通过%load_ext导入line_profiler, -f参数是需要分析的函数。lprun命令的参数可以通过%lprun?查看。

profile

profile和cProfile是python内置的性能分析工具。可以通过很简单的命令分析每个函数的执行时间。

图中的命令按照累计执行时间进行降序排列,可以较为方便的找出最为耗时的函数。如果想更为直观的展示,还可以安装可视化组件gprof2dot和graphviz,安装方法如下:

pip install gprof2dot
brew install graphviz (for mac)
yum -y install graphviz (for centos)

安装好之后再ipython shell连执行cProfile.run('quick_sort(data, 0, 499)', filename='result.out', sort='cumulative')命令将耗时分析结果导出只result.out文件中,然后在bash shell里执行命令gprof2dot -f pstats result.out | dot -Tpng -o result.png即可生成非常直观的调用耗时图。

当然用到的这个例子不是很好,没有把图像的优势展现出来,在调用非常复杂的时候,自上而下,函数的调用关系和耗时情况一目了然。更多的使用可以查阅python官方文档。

yappi

和profile、cProfile类似,但是yappi对于多线程有着更好的支持,profile不会区分多线程,所以结果看起来会很乱。yappi文档连接:https://bitbucket.org/sumerc/yappi/wiki/ApiYappi

使用方法如下:

import yappi
yappi.clear_stats()
yappi.start()
quick_sort(data, 0, 499)
yappi.stop()
stats = yappi.convert2pstats(yappi.get_func_stats())
stats.sort_stats("cumulative")
stats.print_stats()

在python shell连执行这些就可以把要分析的函数按照累计执行时间排序后打印出来,当然yappi同样可以用图像表示,在python shell里执行stats.dump_stats('result.out')把耗时数据导出到result.out中,然后在bash shell里面执行gprof2dot -f pstats result.out | dot -Tpng -o result.png,生成图像如下:

当然yappi.start中还可以添加一些参数是否分析多线程以及builtin函数。

posted @ 2016-07-07 22:34  腩啵兔子  阅读(7221)  评论(0编辑  收藏  举报