有时候需要去优化Python端代码的性能,所以需要先找到瓶颈在哪里。好在这个事做起来特别方便。
一般先找出哪些函数是瓶颈,然后再看看那些函数里面时间都具体花在哪些行上了。Python里面提供的cProfiler可以解决第一个问题,另外这里line profiler[0]可以解决第二个问题。
第一步可以这样(test.py):
def bar(n):
a = 0
for i in range(n):
a += i**2
return a
def foo():
ret = 0
for i in range(1000):
ret += bar(i)
return ret
def c_profile(codestr):
import cProfile
p = cProfile.Profile()
p.run(codestr)
p.print_stats()
if __name__ == '__main__':
c_profile("foo()")
# python test.py
输出
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 0.157 0.157 :1()
1000 0.157 0.000 0.157 0.000 test.py:10(bar)
1 0.000 0.000 0.157 0.157 test.py:16(foo)
1 0.000 0.000 0.157 0.157 {built-in method exec}
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
可以看出所有时间都基本花在了foo和bar两个函数里。然后修改一下代码来逐行地对foo和bar进行分析:
@profile
def bar(n):
a = 0
for i in range(n):
a += i**2
return a
@profile
def foo():
ret = 0
for i in range(1000):
ret += bar(i)
return ret
if __name__ == '__main__':
foo()
# kernprof -lv test.py
输出:
Timer unit: 1e-06 s
Total time: 0.525531 s
File: test.py
Function: bar at line 9
Line # Hits Time Per Hit % Time Line Contents
==============================================================
9 @profile
10 def bar(n):
11 1000 495 0.5 0.1 a = 0
12 500500 169433 0.3 32.2 for i in range(n):
13 499500 355155 0.7 67.6 a += i ** 2
14 1000 448 0.4 0.1 return a
Total time: 0.804509 s
File: test.py
Function: foo at line 16
Line # Hits Time Per Hit % Time Line Contents
==============================================================
16 @profile
17 def foo():
18 1 5 5.0 0.0 ret = 0
19 1001 552 0.6 0.1 for i in range(1000):
20 1000 803951 804.0 99.9 ret += bar(i)
21 1 1 1.0 0.0 return ret
从上面的数据就可以清楚找到瓶颈在哪里了。
====