1. 性能调优
在代码可以实现功能且健壮不出错的前提下,我们往往会有优化性能的需求
性能调优大约可以在运行时间和运行内存占用两方面来考量,下面介绍的工具定位精度由粗到细,也分为这两个方面
1.1. 测试整体运行时间
Python中的timeit是测试代码执行效率的工具.可以用命令行直接测试脚本,也可以测试代码字符串的效率,当然最简单的还是直接用ipython的内置timeit魔法命令测某段代码的效率
import timeit t = timeit.Timer('map(lambda x: x**2,range(1000))') t.timeit() 0.404256040987093 !python -m timeit -s "map(lambda x: x**2,range(1000))" 100000000 loops, best of 3: 0.00833 usec per loop 1.2. 函数级性能瓶颈定位
python的标准库中有一个可以实现性能瓶颈定位的模块叫cprofile,他是一个开销极小的C扩展.用它可以实现函数级的性能分析,配合pstats模块还可以输出分析报告
1.2.1. 使用单独模块分析
%%writefile src/C3/profile_test.py def foo():     sum = 0     for i in range(10000):         sum += i     return sum if __name__=="__main__":     foo() Overwriting src/C3/profile_test.py %%writefile src/C3/profile_test.py def foo():     sum = 0     for i in range(10000):         sum += i     return sum if __name__=="__main__":     try :         import profile     except:         import cProfile as profile      profile.run("foo()") Overwriting src/C3/profile_test.py !python src/C3/profile_test.py          5 function calls in 0.002 seconds     Ordered by: standard name     ncalls  tottime  percall  cumtime  percall filename:lineno(function)         1    0.000    0.000    0.001    0.001 :0(exec)         1    0.001    0.001    0.001    0.001 :0(setprofile)         1    0.000    0.000    0.001    0.001 <string>:1(<module>)         1    0.000    0.000    0.002    0.002 profile:0(foo())         0    0.000             0.000          profile:0(profiler)         1    0.001    0.001    0.001    0.001 profile_test.py:1(foo) 1.2.2. 使用命令行分析
0.404256040987093 00.404256040987093 10.404256040987093 20.404256040987093 31.2.3. 统计项说明
| 统计项 | 说明 | 
|---|---|
| ncalls | 函数被调用次数 | 
| tottime | 函数总计运行时间,不含调用函数运行时间 | 
| cumtime | 函数总计运行时间,含调用的函数运行时间 | 
| percall | 函数运行一次平均时间,等于tottime(cumtime)/ncalls | 
| filename:lineno | 函数所在文件名,函数的行号,函数名 | 
1.2.4. 与pstats结合提供多种形式的报表
0.404256040987093 40.404256040987093 50.404256040987093 60.404256040987093 7stats有许多函数,可以提供不同的报表
- stats函数说明
| 函数 | 说明 | 
|---|---|
| strip_dirs() | 除去文件名前名的路径信息 | 
| add(filename,[...]) | 把profile输出的文件加入stats实例中统计 | 
| dump_stats(filename) | 把stats统计结果保存到文件 | 
| sort_stats(key,[...]) | 最重要的,可以给profile统计结果排序 | 
| reverse_order() | 数据反排序 | 
| print_stats([restriction,...]) | 把报表输出到stdout | 
| print_callers([restriction,...]) | 输出调用指定函数的相关信息 | 
| print_callees([restriction,...]) | 输出指定函数调用过的函数的相关信息 | 
- sort_stats可接受的参数
| 参数 | 说明 | 
|---|---|
| ncalls | 被调次数 | 
| cumulative | 函数运行总时间 | 
| file | 文件名 | 
| module | 模块名 | 
| pcalls | 简单统计 | 
| line | 行号 | 
| name | 函数名 | 
| nfl | name,file,line | 
| stdname | 标准函数名 | 
| time | 函数内部运行时间 | 
1.3. 语句级性能瓶颈定位
cprofiler只能追踪到哪个函数是性能瓶颈,而函数中哪条语句是性能瓶颈就追踪不到了,对于语句级性能瓶颈定位,python并没有官方工具,但github上有位大神制作了line_profiler,这个工具可以实现这一功能,它也几乎可以说是python的半标准工具之一了.
因为不是标准库中的内容,所以需要pip安装.
使用方法十分简单,在需要分析的函数上面加上装饰器@profile即可(注意不用import任何东西,这条装饰器在定位好后应该删除以保证代码可以运行)
0.404256040987093 80.404256040987093 9!python -m timeit -s "map(lambda x: x**2,range(1000))" 0!python -m timeit -s "map(lambda x: x**2,range(1000))" 11.4. 内存分析
memory_profiler是用来分析内存使用情况和追踪内存泄露的工具.它用法比较接近line_profiler
由于不是标准库中的模块,它需要pip安装.
需要注意的是windows下需要在script文件夹下将mprof文件改名为mprof.py并在同一目录下创建一个mprof.bat文件编辑为如下内容
!python -m timeit -s "map(lambda x: x**2,range(1000))" 2它的使用及其简单:
!python -m timeit -s "map(lambda x: x**2,range(1000))" 3!python -m timeit -s "map(lambda x: x**2,range(1000))" 4之后使用
!python -m timeit -s "map(lambda x: x**2,range(1000))" 5就可以看到详细结果了
指定精度可以在profile装饰器后面加上参数 如: @profile(precision=4)
mprof工具类似kernprof,用它可以输出更加友好的统计分析页面
!python -m timeit -s "map(lambda x: x**2,range(1000))" 6!python -m timeit -s "map(lambda x: x**2,range(1000))" 7!python -m timeit -s "map(lambda x: x**2,range(1000))" 8!python -m timeit -s "map(lambda x: x**2,range(1000))" 9100000000 loops, best of 3: 0.00833 usec per loop 0100000000 loops, best of 3: 0.00833 usec per loop 11.5. 对象分析及追踪(windows下不能用)
Objgraph可以实现对象分析和追踪,它也是用pip安装,不过它依赖xdot(pip 安装) 和graphviz(brew安装)
它可以实现的功能有:
- 统计
- 定义过滤对象
- 遍历和显示对象图
100000000 loops, best of 3: 0.00833 usec per loop 2100000000 loops, best of 3: 0.00833 usec per loop 3100000000 loops, best of 3: 0.00833 usec per loop 4100000000 loops, best of 3: 0.00833 usec per loop 5于是你可以看到图了





 
		 
		

还没有评论,来说两句吧...