使用cProfiler对Python程序进行性能分析

介绍

profiler是一个程序,用来描述运行时的程序性能,并且从不同方面提供统计数据加以表述。
Python中含有3个模块提供这样的功能,分别是cProfile,profile和pstats。这些分析器提供的是对Python程序的确定性分析。同时也提供一系列的报表生成工具,允许用户快速地检查分析结果。

Python标准库提供了3个不同的性能分析器:
- cProfile,推荐给大部分的用户,是C的一个扩展应用,因为其合理的运行开销,所以适合分析运行时间较长的。是基于lsprof。
- profile,一个纯python模块,它的接口和cProfile一致。在分析程序时,增加了很大的运行开销。如果你想扩展profiler的功能,可以试着继承这个模块
- hotshot, 一个试验性的c模块,关注减少分析时的运行开销,但是是以需要更长的数据后处理的次数为代价。不过这个模块不再被维护,也有可能在新的python版本中被弃用。

实践

源码

from random import randint
from cProfile import Profile
import pstats

def insert_sort(data):
    result=[]
    for value in data:
        insert_value(result,value)
    return result

def insert_value(result,value):
    for i,existing in enumerate(result):
        if existing > value:
            result.insert(i,value)
            return
    result.append(value)

def main():
    max_size=10**4
    data=[randint(0,max_size) for _ in range(max_size)]
    test= lambda :insert_sort(data)
    return test

使用cProfile进行分析

分析代码:

def anylize_by_cprofile():
    profile=Profile()
    profile.runcall(main())
    stats=pstats.Stats(profile)
    stats.strip_dirs()  #从所有模块名中去掉无关的路径信息
    stats.sort_stats('cumulative')
    stats.print_stats()

anylize_by_cprofile()

分析结果:

root@native-sunaihua-5-25-18:~/pdb_test# python test.py 
         20003 function calls in 1.195 seconds

   Ordered by: cumulative time

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000    1.195    1.195 test.py:21(<lambda>)
        1    0.003    0.003    1.195    1.195 test.py:5(insert_sort)
    10000    1.174    0.000    1.191    0.000 test.py:11(insert_value)
     9992    0.018    0.000    0.018    0.000 {method 'insert' of 'list' objects}
        8    0.000    0.000    0.000    0.000 {method 'append' of 'list' objects}
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}

结果说明
- ncalls:总的调用次数
- totime:消耗的时间,不包括调用其他函数的时间
- tottime percall:每次调用该函数的时间,不包括调用其他函数的时间
- cumtime:消耗的总时间,包括调用其他函数的实践
- cumtime percall:每次调用该函数的时间,包括调用其他函数的时间

不足:
上面的信息只是列出了每个函数的执行信息,但是没有列出调用关系,如果想查看调用关系,可以执行stats.print_callers()方法,结果如下:

Ordered by: cumulative time

Function                                          was called by...
                                                      ncalls  tottime  cumtime
test.py:21(<lambda>)                              <-
test.py:5(insert_sort)                            <-       1    0.004    1.221  test.py:21(<lambda>)
test.py:11(insert_value)                          <-   10000    1.199    1.217  test.py:5(insert_sort)
{method 'insert' of 'list' objects}               <-    9992    0.018    0.018  test.py:11(insert_value)
{method 'append' of 'list' objects}               <-       8    0.000    0.000  test.py:11(insert_value)
{method 'disable' of '_lsprof.Profiler' objects}  <-

其他方式

在GUI的系统中,还可以通过更加高级的方式进行分析与调试,例如使用RunSnakeRun,或是KCachegrind,详细说明可参见:http://blog.jobbole.com/52090/

你可能感兴趣的:(Python)