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) 文件名,列数,方法名