python 优化利器(一)cProfile 查询消耗时间最久的方法函数

VIM 的作者Bram Moolenaar在一篇叫高效文本编辑器的7个习惯的ppt中有这么一段话。
Three basic steps
1. Detect inefficiency
2. Find a quicker way
3. Make it a habit

1.检测哪里效率低下
2.找到一种更快的方法
3.养成习惯

这3个步骤可谓是大道至简。放之四海而皆准。
不止适用于vim,一样适用于python以及其他语言,也适用于现实生活。
这简单的道理很多人都懂,但是却有很多人没有贯彻。
一遇到性能问题就胡乱猜测,毫无目的,无针对性。

性能问题也符合20/80规则。即20%的代码引起了80%的性能损耗。
可能有很多地方可以修修补补来优化,但是却是无关痛痒的性能提升,效果不明显,还经常把代码搞的一团糟。
感觉是不可靠的,要用数据说话。
通过profile可以快速定位到热点。针对热点来进行优化,往往能收到奇效。

python自带了profile模块。还自带用c语言写的cProfile。
使用很简单,在命令行中 python -m cProfile xxx.py。

cprofile_test.py

#!/usr/bin/python
# coding: utf-8

# -*- coding: utf-8 -*-


import time



def primes(n):

    if n == 2:

        return [2]

    elif n < 2:

        return []

    s = []

    for i in range(3, n+1):

        if i % 2 != 0:

            s.append(i)

    mroot = n ** 0.5

    half = (n + 1) / 2 - 1

    i = 0

    m = 3

    while m <= mroot:

        if s[i]:

            j = (m * m - 3) / 2

            s[j] = 0

            while j < half:

                s[j] = 0

                j += m

        i = i + 1

        m = 2 * i + 3

    l = [2]

    for x in s:

        if x:

            l.append(x)

    return l



def benchmark():

    start = time.time()

    for _ in xrange(40):

        count = len(primes(1000))

    end = time.time()

    print "Benchmark duration: %r seconds" % (end-start)



benchmark()

检测时间消耗

python -m cProfile -s cumulative cprofile_test.py

-s cumulative 可按时间进行排序

[root@k8s-node-1 alex]# python -m cProfile -s cumulative cprofile_test.py 
Benchmark duration: 15.244712114334106 seconds
         23139965 function calls in 15.245 seconds

   Ordered by: cumulative time

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000   15.245   15.245 cprofile_test.py:7(<module>)
        1    0.150    0.150   15.245   15.245 cprofile_test.py:67(benchmark)
       40   11.086    0.277   15.095    0.377 cprofile_test.py:11(primes)
       40    2.897    0.072    2.897    0.072 {range}
 23139840    1.112    0.000    1.112    0.000 {method 'append' of 'list' objects}
       40    0.000    0.000    0.000    0.000 {len}
        2    0.000    0.000    0.000    0.000 {time.time}
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}

参数说明:(以primes为例)
Benchmark duration: 15.244712114334106 seconds 输出结果
23139965 function calls in 15.245 seconds
23139965 此调用,共花费15.245 seconds
ncalls : 函数执行次数 primes执行了40次
cumtime (cumulative time):累积时间,包括子函数。这里说的子函数,就是在函数中调用其它的函数。primes用了15.095秒。
tottime : 不包含子函数的时间,即primes用了11.086秒,不包括函数里面的子函数(range,append)的时间
11.086 + (2.897 + 1.112) = 15.095 ,此时间最为重要
filename:lineno(function) 文件名,列数,方法名

猜你喜欢

转载自blog.csdn.net/budong282712018/article/details/80279424