python代码性能分析工具介绍

分析所写程序性能是写代码的基本功。我们通常会通过设置起始时间与结束时间点来监测代码片段运行耗时。但是这种naive的方法需要修改源代码,会带来额外的工作量。今天主要介绍几个性能分析工具,及其实践技巧。
以我们熟悉的两种排序算法作为讲解例子,来看看几种工具的使用方法。

import numpy as np
#冒泡
def bubble_sort(data):
    leng=len(data)
    for i in range(leng):
        for j in range(leng-i-1):
            if data[j]>data[j+1]:
                temp=data[j]
                data[j]=data[j+1]
                data[j+1]=temp
    return data
    
#快排
def quick_sort(data):
    if len(data)<=1:
        return data
    pivot=data[int(len(data)/2)]
    left=[x for x in data if x<pivot]
    right=[x for x in data if x>pivot]
    pivot_=[x for x in data if x==pivot]
    return quick_sort(left)+pivot_+quick_sort(right)
            

time

time模块可以直接调用查看函数运行用时

b=list(np.random.rand(1000))
%time t=quick_sort(b)
CPU times: user 17.1 ms, sys: 97 µs, total: 17.2 ms
Wall time: 16.3 ms
%time t=bubble_sort(b)
CPU times: user 85 ms, sys: 0 ns, total: 85 ms
Wall time: 84.3 ms

time 输出的well time 是实际耗时。

timeit

%timeit -n 100 -r 5 quick_sort(b)
1.28 ms ± 145 µs per loop (mean ± std. dev. of 5 runs, 100 loops each)
%timeit -n 100 -r 5 bubble_sort(b)
29.3 ms ± 291 µs per loop (mean ± std. dev. of 5 runs, 100 loops each)

上述命令重复跑了100遍,每遍跑函数5次,返回每一遍对应平均耗时.

但是为什么使用%time每一遍对应耗时跟%timeit对应耗时相差如此巨大?

line_profiler

上述性能分析方法只能显示整个函数的耗时,为了知道函数中具体每行代码耗时情况,我们可以使用line_profiler

一般来说,使用line_profiler需要先在待测函数上添加@profile装饰器,但是在jupyterlab或者ipython交互环境中,首先使用

%load_ext line_profiler

引入line_profiler模块,然后使用命令

%lprun -f your_function your_function()

来输出每行具体运行性能,这样就比加装饰器更加方便了。

%load_ext line_profiler
%lprun -f bubble_sort bubble_sort(b)
Timer unit: 1e-06 s

Total time: 0.258086 s
File: <ipython-input-2-5f5f09499d34>
Function: bubble_sort at line 2

Line #      Hits         Time  Per Hit   % Time  Line Contents
==============================================================
     2                                           def bubble_sort(data):
     3         1          5.0      5.0      0.0      leng=len(data)
     4      1001        244.0      0.2      0.1      for i in range(leng):
     5    500500     109484.0      0.2     42.4          for j in range(leng-i-1):
     6    499500     148353.0      0.3     57.5              if data[j]>data[j+1]:
     7                                                           temp=data[j]
     8                                                           data[j]=data[j+1]
     9                                                           data[j+1]=temp
    10         1          0.0      0.0      0.0      return data
%lprun -f quick_sort quick_sort(b)
Timer unit: 1e-06 s

Total time: 0.022512 s
File: <ipython-input-3-63a5655acfad>
Function: quick_sort at line 2

Line #      Hits         Time  Per Hit   % Time  Line Contents
==============================================================
     2                                           def quick_sort(data):
     3      1023       2376.0      2.3     10.6      if len(data)<=1:
     4       512        825.0      1.6      3.7          return data
     5       511       1424.0      2.8      6.3      pivot=data[int(len(data)/2)]
     6       511       6093.0     11.9     27.1      left=[x for x in data if x<pivot]
     7       511       5259.0     10.3     23.4      right=[x for x in data if x>pivot]
     8       511       5448.0     10.7     24.2      pivot_=[x for x in data if x==pivot]
     9       511       1087.0      2.1      4.8      return quick_sort(left)+pivot_+quick_sort(right)

参数解释:

  • Hits:当前行运行次数
  • Time:该行总共运行耗时
  • Per Hit: 平均每次运行耗时
  • % Time: 当前行运行耗时对总耗时占比

工作原理

%lprun一些关键字

  • -f:待测函数,输入格式是your_func your_func(args)
  • -T:save the profile report as a file
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值