【感谢 贱圣OMG 的热心翻译。如果其他朋友也有不错的原创或译文,可以提交到伯乐在线。】
虽然不是所有的Python程序都需要严格的性能分析,不过知道如何利用Python生态圈里的工具来分析性能,也是不错的。
分析一个程序的性能,总结下来就是要回答4个问题:
- 它运行的有多快?
- 它的瓶颈在哪?
- 它占用了多少内存?
- 哪里有内存泄漏?
接下来,我们会着手使用一些很棒的工具,来帮我们回答这些问题。
粗粒度的计算时间
我们先来用个很快的方法来给我们的代码计时:使用unix的一个很好的功能 time。
1 2 3 4 5 |
$ time python yourprogram.py real 0m1.028s user 0m0.001s sys 0m0.003s |
关于这3个测量值的具体含义可以看StackOverflow上的帖子,但是简要的说就是:
- real:代表实际花费的时间
- user::代表cpu花费在内核外的时间
- sys:代表cpu花费在内核以内的时间
通过把sys和user时间加起来可以获得cpu在你的程序上花费的时间。
如果sys和user加起来的时间比real时间要小很多,那么你可以猜想你的程序的大部分性能瓶颈应该是IO等待的问题。
用上下文管理器来细粒度的测量时间
我接下来要使用的技术就是让你的代码仪器化以让你获得细粒度的时间信息。这里是一个计时方法的代码片段:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
import time class Timer(object): def __init__(self, verbose=False): self.verbose = verbose def __enter__(self): self.start = time.time() return self def __exit__(self, *args): self.end = time.time() self.secs = self.end - self.start self.msecs = self.secs * 1000 # millisecs if self.verbose: print 'elapsed time: %f ms' % self.msecs |
为了使用它,将你想要测量时间的代码用Python关键字with和Timer上下文管理器包起来。它会在你的代码运行的时候开始计时,并且在执行结束的完成计时。
下面是一个使用它的代码片段:
1 2 3 4 5 6 7 8 9 10 11 |
from timer import Timer from redis import Redis rdb = Redis() with Timer() as t: rdb.lpush("foo", "bar") print "=> elasped lpush: %s s" % t.secs with Timer as t: rdb.lpop("foo") print "=> elasped lpop: %s s" % t.secs |
我会经常把这些计时器的输入记录进一个日志文件来让我知道程序的性能情况。
用分析器一行一行地计时和记录执行频率
Robert Kern有一个很棒的项目名叫 line_profiler。我经常会用它来测量我的脚本里每一行代码运行的有多快和运行频率。
为了用它,你需要通过pip来安装这个Python包:
1 |
$ pip install line_profiler |
在你安装好这个模块之后,你就可以使用line_profiler模块和一个可执行脚本kernprof.py。
为了用这个工具,首先需要修改你的代码,在你想测量的函数上使用@profiler装饰器。不要担心,为了用这个装饰器你不需要导入任何其他的东西。Kernprof.py这个脚本可以在你的脚本运行的时候注入它的运行时。
Primes.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
@profile def primes(n): if n==2: return [2] elif n<2: return [] s=range(3,n+1,2) mroot = n ** 0.5 half=(n+1)/2-1 i=0 m=3 e="@贱圣OMG" href="http://weibo.com/fwgisbug" target="_blank">贱圣OMG 的热心翻译。如果其他朋友也有不错的原创或译文,可以提交到伯乐在线。】
虽然不是所有的Python程序都需要严格的性能分析,不过知道如何利用Python生态圈里的工具来分析性能,也是不错的。 分析一个程序的性能,总结下来就是要回答4个问题:
接下来,我们会着手使用一些很棒的工具,来帮我们回答这些问题。
粗粒度的计算时间我们先来用个很快的方法来给我们的代码计时:使用unix的一个很好的功能 time。
关于这3个测量值的具体含义可以看StackOverflow上的帖子,但是简要的说就是:
通过把sys和user时间加起来可以获得cpu在你的程序上花费的时间。 如果sys和user加起来的时间比real时间要小很多,那么你可以猜想你的程序的大部分性能瓶颈应该是IO等待的问题。
用上下文管理器来细粒度的测量时间我接下来要使用的技术就是让你的代码仪器化以让你获得细粒度的时间信息。这里是一个计时方法的代码片段:
为了使用它,将你想要测量时间的代码用Python关键字with和Timer上下文管理器包起来。它会在你的代码运行的时候开始计时,并且在执行结束的完成计时。 下面是一个使用它的代码片段:
我会经常把这些计时器的输入记录进一个日志文件来让我知道程序的性能情况。
用分析器一行一行地计时和记录执行频率Robert Kern有一个很棒的项目名叫 line_profiler。我经常会用它来测量我的脚本里每一行代码运行的有多快和运行频率。 为了用它,你需要通过pip来安装这个Python包:
在你安装好这个模块之后,你就可以使用line_profiler模块和一个可执行脚本kernprof.py。 为了用这个工具,首先需要修改你的代码,在你想测量的函数上使用@profiler装饰器。不要担心,为了用这个装饰器你不需要导入任何其他的东西。Kernprof.py这个脚本可以在你的脚本运行的时候注入它的运行时。
|