Python程序的性能分析指南
admin
2023-07-31 00:48:36
0

【感谢 贱圣OMG 的热心翻译。如果其他朋友也有不错的原创或译文,可以提交到伯乐在线。】

 

虽然不是所有的Python程序都需要严格的性能分析,不过知道如何利用Python生态圈里的工具来分析性能,也是不错的。

分析一个程序的性能,总结下来就是要回答4个问题:

  1. 它运行的有多快?
  2. 它的瓶颈在哪?
  3. 它占用了多少内存?
  4. 哪里有内存泄漏?

接下来,我们会着手使用一些很棒的工具,来帮我们回答这些问题。

 

粗粒度的计算时间

我们先来用个很快的方法来给我们的代码计时:使用unix的一个很好的功能 time。

12345 $ time python yourprogram.py real    0m1.028suser    0m0.001ssys     0m0.003s

关于这3个测量值的具体含义可以看StackOverflow上的帖子,但是简要的说就是:

  • real:代表实际花费的时间
  • user::代表cpu花费在内核外的时间
  • sys:代表cpu花费在内核以内的时间

通过把sys和user时间加起来可以获得cpu在你的程序上花费的时间。

如果sys和user加起来的时间比real时间要小很多,那么你可以猜想你的程序的大部分性能瓶颈应该是IO等待的问题。

 

用上下文管理器来细粒度的测量时间

我接下来要使用的技术就是让你的代码仪器化以让你获得细粒度的时间信息。这里是一个计时方法的代码片段:

12345678910111213141516 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上下文管理器包起来。它会在你的代码运行的时候开始计时,并且在执行结束的完成计时。

下面是一个使用它的代码片段:

1234567891011 from timer import Timerfrom redis import Redisrdb = 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

123456789101112131415161718192021222324 @profiledef primes(n):     if n==2:        return [2]    elif n<2:        return []    s=range(3,n+1,2)    mroot = n ** 0.5    half=(n+1)/21    i=0    m=3e=\”@贱圣OMG\” href=\”http://weibo.com/fwgisbug\” target=\”_blank\”>贱圣OMG 的热心翻译。如果其他朋友也有不错的原创或译文,可以提交到伯乐在线。】

 

虽然不是所有的Python程序都需要严格的性能分析,不过知道如何利用Python生态圈里的工具来分析性能,也是不错的。

分析一个程序的性能,总结下来就是要回答4个问题:

  1. 它运行的有多快?
  2. 它的瓶颈在哪?
  3. 它占用了多少内存?
  4. 哪里有内存泄漏?

接下来,我们会着手使用一些很棒的工具,来帮我们回答这些问题。

 

粗粒度的计算时间

我们先来用个很快的方法来给我们的代码计时:使用unix的一个很好的功能 time。

12345 $ time python yourprogram.py real    0m1.028suser    0m0.001ssys     0m0.003s

关于这3个测量值的具体含义可以看StackOverflow上的帖子,但是简要的说就是:

  • real:代表实际花费的时间
  • user::代表cpu花费在内核外的时间
  • sys:代表cpu花费在内核以内的时间

通过把sys和user时间加起来可以获得cpu在你的程序上花费的时间。

如果sys和user加起来的时间比real时间要小很多,那么你可以猜想你的程序的大部分性能瓶颈应该是IO等待的问题。

 

用上下文管理器来细粒度的测量时间

我接下来要使用的技术就是让你的代码仪器化以让你获得细粒度的时间信息。这里是一个计时方法的代码片段:

12345678910111213141516 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上下文管理器包起来。它会在你的代码运行的时候开始计时,并且在执行结束的完成计时。

下面是一个使用它的代码片段:

1234567891011 from timer import Timerfrom redis import Redisrdb = 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

123456789101112131415161718192021222324 @profiledef primes(n):     if n==2:        return [2]    elif n<2:        return []    s=range(3,n+1,2)    mroot = n ** 0.5    half=(n+1)/21    i=0    m=3crayon-h\”>    while m

相关内容

热门资讯

Mobi、epub格式电子书如... 在wps里全局设置里有一个文件关联,打开,勾选电子书文件选项就可以了。
500 行 Python 代码... 语法分析器描述了一个句子的语法结构,用来帮助其他的应用进行推理。自然语言引入了很多意外的歧义,以我们...
定时清理删除C:\Progra... C:\Program Files (x86)下面很多scoped_dir开头的文件夹 写个批处理 定...
scoped_dir32_70... 一台虚拟机C盘总是莫名奇妙的空间用完,导致很多软件没法再运行。经过仔细检查发现是C:\Program...
65536是2的几次方 计算2... 65536是2的16次方:65536=2⁶ 65536是256的2次方:65536=256 6553...
小程序支付时提示:appid和... [Q]小程序支付时提示:appid和mch_id不匹配 [A]小程序和微信支付没有进行关联,访问“小...
pycparser 是一个用... `pycparser` 是一个用 Python 编写的 C 语言解析器。它可以用来解析 C 代码并构...
微信小程序使用slider实现... 众所周知哈,微信小程序里面的音频播放是没有进度条的,但最近有个项目呢,客户要求音频要有进度条控制,所...
Apache Doris 2.... 亲爱的社区小伙伴们,我们很高兴地向大家宣布,Apache Doris 2.0.0 版本已于...
python清除字符串里非数字... 本文实例讲述了python清除字符串里非数字字符的方法。分享给大家供大家参考。具体如下: impor...