zltzlt 发表于 2020-1-1 15:14:07

Python 小技巧 045:性能分析(二)—— line_profiler

本帖最后由 zltzlt 于 2020-1-1 15:21 编辑

Python 性能分析器 —— line_profiler

line_profiler 和 cProfiler 类似,区别是 line_profiler 是第三方库,而且它会逐行分析代码的用时,比 cProfiler 更强大。

1. 安装

打开 https://www.lfd.uci.edu/~gohlke/pythonlibs/#line_profiler,下载符合自己 Python 版本的 line_profiler .whl 文件:



下载完之后打开 cmd ,切换到文件位置,执行以下命令:

pip install {.whl 文件名}

2. 使用方法

下面是 demo.py 的内容(求 100 以内哪两个数相加为 100 的程序,双重 for 循环):

# -*- coding: utf-8 -*-

@profile    # 加 @profile 的函数表示需要进行分析
def demo():
    task = []

    for a in range(0, 101):
      for b in range(0, 101):
            if a + b == 100:
                task.append((a, b))
    return task


if __name__ == '__main__':
    demo()

cmd 执行命令:

kernprof -l -v demo.py

其中 -l 表示逐行分析,-v 表示输出分析结果。

执行这段命令会生成一个 demo.py.lprof,后期可以对该文件进行分析。

分析结果:

Wrote profile results to demo.py.lprof
Timer unit: 1e-07 s

Total time: 0.0065966 s
File: demo.py
Function: demo at line 3

Line #      Hits         TimePer Hit   % TimeLine Contents
==============================================================
   3                                           @profile
   4                                           def demo():
   5         1         69.0   69.0      0.1      task = []
   6
   7       102      287.0      2.8      0.4      for a in range(0, 101):
   8   10302      30200.0      2.9   45.8          for b in range(0, 101):
   9   10201      34938.0      3.4   53.0            if a + b == 100:
    10       101      468.0      4.6      0.7                  task.append((a, b))
    11         1          4.0      4.0      0.0      return task


其中:


[*]Total time 表示代码总用时。
[*]File 表示分析的文件名。
[*]Function 表示测试的函数。
[*]Line # 表示行号。
[*]Hits 表示本行调用的次数。
[*]Time 表示本行总执行时间。
[*]Per Hit 表示本行执行一次的用时,是 Time 除以 Hits 的结果。
[*]% Time 表示本行代码占了它所在函数的消耗的时间百分比。


可以看出在 demo 函数中最消耗时间的是判断 a + b 是否等于 100,占用了 50.5% 的时间。

之后对代码进行优化:

@profile
def demo():
    task = []

    for a in range(0, 101):
      b = 100 - a
      task.append((a, b))
    return task


if __name__ == '__main__':
    demo()

再次进行分析:

Wrote profile results to demo.py.lprof
Timer unit: 1e-07 s

Total time: 0.0001048 s
File: demo.py
Function: demo at line 3

Line #      Hits         TimePer Hit   % TimeLine Contents
==============================================================
   3                                           @profile
   4                                           def demo():
   5         1         31.0   31.0      3.0      task = []
   6
   7       102      303.0      3.0   28.9      for a in range(0, 101):
   8       101      309.0      3.1   29.5          b = 100 - a
   9       101      402.0      4.0   38.4          task.append((a, b))
    10         1          3.0      3.0      0.3      return task

可以发现总用时及循环体里代码的调用次数减少了。

_2_ 发表于 2020-1-1 16:39:30

沙发!

lijiachen 发表于 2020-7-12 18:28:16

{:10_257:}(又是我)
页: [1]
查看完整版本: Python 小技巧 045:性能分析(二)—— line_profiler