暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

python 内存系列(4)-line_profiler库 统计每行代码的执行次数和执行时间

小儿来一壶枸杞酒泡茶 2021-03-05
2097

line_profiler 时间分析

line_profiler 是一个第三方的模块,需要进行安装才可以使用。它可以统计每行代码的执行次数和执行时间等,时间单位为微妙。

安装:

(.venv) PS D:\code\vscode\py> pip install line-profiler

PS:  如果是windows下,可能安装会有点小麻烦,不过之前安装相关的加密解密库的时候已安装处理,应该也没什么大问题。主要是需要安装C++ 编译器。以前通常就是直接的安装一个VC。

1、@profile装饰器应用示例(不需要import任何包):

  • line_profiler_ceshi.py

@profile
def randomlist(n):
  lists = []
  l = [random.random() for i in range(n)]
  l.sort()
  for v in l:
      lists.append(v)
  return lists


@profile
def randomlist_2():
   lists = []
   for v in l:
      lists.append(v)


@profile
def run():
  randomlist(200000)
  randomlist_2(200000)


if __name__ == '__main__':
  run()



然后通过通过下面的命令获得关于random_sort2函数的逐行描述:

kernprof -l -v .\line_profiler_ceshi.py

PS:

  • -l 表示逐行解释,
  • v  表示输出详细结果。
  • 通过这种方法,我们看到构建数组消耗了44%的计算时间,而sort()方法消耗了剩余的56%的时间。

提示相关的程序 运行,运行一下吧。

执行结果:

(.venv) PS D:\code\vscode\py>  kernprof -l -v .\line_profiler_ceshi.py
Wrote profile results to line_profiler_ceshi.py.lprof
Timer unit: 1e-07 s

Total time: 0.306481 s
File: .\line_profiler_ceshi.py
Function: randomlist at line 14

Line #      Hits         Time  Per Hit   % Time  Line Contents
==============================================================
    14                                           @profile
    15                                           def randomlist(n):
    16         1         14.0     14.0      0.0      lists = []
    17         1     384313.0 384313.0     12.5      l = [random.random() for i in range(n)]
    18         1     676791.0 676791.0     22.1      l.sort()
    19    200001     967809.0      4.8     31.6      for v in l:
    20    200000    1035876.0      5.2     33.8          lists.append(v)
    21         1          6.0      6.0      0.0      return lists


  • Line:代码行号
  • Hits:表示每行代码运行次数
  • Time:每行代码运行总时间(时间单位为微妙)
  • Per Hits:每行代码运行一次需要时间 (时间单位为微妙)
  • % Time:每行代码运行时间百分比
  • line Contents:每行代码内容

PS:如果需要分析多个函数直接的加装饰器就可以

@profile
def foo():
    task = []

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


@profile
def run():
    for item in foo():
        pass


if __name__ == '__main__':
    run()


2、import line_profiler的代码的方式运行分析:

  • line_profiler_ceshi.py
import line_profiler
import random


def randomlist(n):
  lists = []
  l = [random.random() for i in range(n)]
  l.sort()
  for v in l:
      lists.append(v)
  return lists


if __name__ == "__main__":
  profile = line_profiler.LineProfiler(randomlist)  # 把函数传递到性能分析器
  profile.enable()  # 开始分析
  randomlist(200000)
  profile.disable()  # 停止分析
  profile.print_stats()  # 打印出性能分析结果


执行的结果是:

  • Line:代码行号
  • Hits:表示每行代码运行次数
  • Time:每行代码运行总时间
  • Per Hits:每行代码运行一次需要时间
  • % Time:每行代码运行时间百分比
  • line Contents:每行代码内容
Timer unit: 1e-07 s

Total time: 0.292393 s
File: d:/code/vscode/py/line_profiler_ceshi.py
Function: randomlist at line 15

Line #      Hits         Time  Per Hit   % Time  Line Contents     
==============================================================     
  15                                           def randomlist(n):
  16         1         12.0     12.0      0.0      lists = []
  17         1     375378.0 375378.0     12.8      l = [random.random() for i in range(n)]
  18         1     671413.0 671413.0     23.0      l.sort()
  19    200001     915280.0      4.6     31.3      for v in l:
  20    200000     961843.0      4.8     32.9          lists.append(v)
  21         1          5.0      5.0      0.0      return lists

(.venv) PS D:\code\vscode\py> 

3、import line_profiler 改造成一个装饰器:

  • line_profiler_ceshi.py
import random
from line_profiler import LineProfiler
from functools import wraps

# 查询接口中每行代码执行的时间


# 查询接口中每行代码执行的时间
def func_line_time(f):
 @wraps(f)
 def decorator(*args, **kwargs):
     func_return = f(*args, **kwargs)
     profile = LineProfiler()
     profile.enable()  # 开始分析
     profile_wrap = profile(f)
     profile_wrap(*args, **kwargs)
     profile.disable()  # 停止分析
     profile.print_stats()  # 打印出性能分析结果
     return func_return
 return decorator


@func_line_time
def randomlist(n):
 lists = []
 l = [random.random() for i in range(n)]
 l.sort()
 for v in l:
     lists.append(v)
 return lists


if __name__ == "__main__":
 randomlist(200000)

输出结果:

Timer unit: 1e-07 s

Total time: 0.299915 s
File: d:/code/vscode/py/line_profiler_ceshi.py
Function: randomlist at line 34

Line #      Hits         Time  Per Hit   % Time  Line Contents
==============================================================
 34                                           @func_line_time
 35                                           def randomlist(n):
 36         1         15.0     15.0      0.0      lists = []
 37         1     374605.0 374605.0     12.5      l = [random.random() for i in range(n)]
 38         1     696941.0 696941.0     23.2      l.sort()
 39    200001     947125.0      4.7     31.6      for v in l:
 40    200000     980459.0      4.9     32.7          lists.append(v)
 41         1          6.0      6.0      0.0      return lists

(.venv) PS D:\code\vscode\py> 

多个函数需要函数的示例:

'''
Author: 小钟同学
objectDescription: 项目描述
Date: 2021-03-05 14:07:13
LastEditors: 308711822@qq.com
LastEditTime: 2021-03-05 15:01:25
FilePath: \py\line_profiler_ceshi.py
Version: 1.0
'
''


import random
from line_profiler import LineProfiler
from functools import wraps

# 查询接口中每行代码执行的时间


# 查询接口中每行代码执行的时间
def func_line_time(f):
    @wraps(f)
    def decorator(*args, **kwargs):
        func_return = f(*args, **kwargs)
        profile = LineProfiler()
        profile.enable()  # 开始分析
        profile_wrap = profile(f)
        profile_wrap(*args, **kwargs)
        profile.disable()  # 停止分析
        profile.print_stats()  # 打印出性能分析结果
        return func_return
    return decorator


@func_line_time
def randomlist(n):
    lists = []
    l = [random.random() for i in range(n)]
    l.sort()
    for v in l:
        lists.append(v)
    return lists


@func_line_time
def randomlist_324234(n):
    lists = []
    l = [random.random() for i in range(n)]
    l.sort()
    for v in l:
        lists.append(v)
    return lists


if __name__ == "__main__":
    randomlist(200000)
    randomlist_324234(454353)


参考资料:

https://testerhome.com/topics/21411

https://www.cnblogs.com/c-x-a/p/10264490.html

https://blog.csdn.net/qq_36097393/article/details/83574269

说明

部分的图或资料来互联网收集整理,如有侵权,烦请联系,我会立即进行删除。

End

纯属个人实践中相关经验之谈,如有纰漏,还希望大佬们多多提点!

小钟同学 | 文  【原创】| QQ:308711822


文章转载自小儿来一壶枸杞酒泡茶,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论