爱上python系列------python性能(二):line_profiler性能分析

Python的性能分析分析十分重要,因为可以给我们优化性能提供可靠的数值参考

Python的性能分析有两个主流工具cProfileline_profiler,前者是python内置的工具,不过不是分析报告特别详细

下面试一下cProfile:

import profile

class cached:
    def __init__(self, fn):
        self.fn = fn
        self.cache = {}
    def __call__(self, *args):
        try:
            return self.cache[args]
        except KeyError:
            self.cache[args] = self.fn(*args)
            return self.cache[args]


@cached
def fib(n):
    if n <= 1:return n
    else:return fib(n-1) + fib(n-2)
def fib_seq(n):
    seq = []
    if n > 0:
        seq.extend(fib_seq(n-1))
    seq.append(fib(n))
    return seq

if __name__ == '__main__':
    #print(fib_seq(20))
    profile.run('print(fib_seq(200)); print')

运行结果如下:

        11521 function calls (8023 primitive calls) in 0.009 seconds

   Ordered by: cumulative time

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
   2505/5    0.005    0.000    0.008    0.002 78797.py:19(fib_seq)
     2500    0.001    0.000    0.001    0.000 {method 'extend' of 'list' objects}
3503/2505    0.001    0.000    0.001    0.000 78797.py:7(__call__)
        5    0.001    0.000    0.001    0.000 {built-in method builtins.print}
      501    0.000    0.000    0.001    0.000 78797.py:15(fib)
     2505    0.000    0.000    0.000    0.000 {method 'append' of 'list' objects}
        1    0.000    0.000    0.000    0.000 cProfile.py:50(create_stats)
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}


   Ordered by: cumulative time

Function                                          was called by...
                                                      ncalls  tottime  cumtime
78797.py:19(fib_seq)                              <-  2500/5    0.005    0.008  78797.py:19(fib_seq)
{method 'extend' of 'list' objects}               <-    2500    0.001    0.001  78797.py:19(fib_seq)
78797.py:7(__call__)                              <-     998    0.000    0.000  78797.py:15(fib)
                                                        2505    0.001    0.001  78797.py:19(fib_seq)
{built-in method builtins.print}                  <- 
78797.py:15(fib)                                  <-     501    0.000    0.001  78797.py:7(__call__)
{method 'append' of 'list' objects}               <-    2505    0.000    0.000  78797.py:19(fib_seq)
cProfile.py:50(create_stats)                      <- 
{method 'disable' of '_lsprof.Profiler' objects}  <-       1    0.000    0.000  cProfile.py:50(create_stats)

注:只写了报告内容,print的内容没有贴出来

我们可以从结果中看到函数调用的概要

不过没法像line_profiler可以按行给出分析报告

line_profiler的使用之前需要安装:

pip3 install line_profiler

安装成功就可以使用了,在使用之前值得一提的是,kernprof是line_profiler工具,在pip3 install line_profiler结束后已经安装好了,不信我们可以试一下:

root@root:/opt/pypy3.7-v7.3.2-linux64# kernprof
Usage: kernprof [-s setupfile] [-o output_file_path] scriptfile [arg] ...

接下来使用kernprof进行分析,在这之前需要建立一个名为tt.py的python文件,内容如:

@profile 
def run(): 
    a = [1]*100 
    b = [x**3 for x in a ] 
    c = [x for x in b] 
    d = c*2 
                     
run()

 接下来就是见证奇迹的时候了:

kernprof -l -v tt.py

结果:

Timer unit: 1e-06 s

Total time: 4e-05 s
File: tt.py
Function: run at line 1

Line #      Hits         Time  Per Hit   % Time  Line Contents
==============================================================
     1                                           @profile 
     2                                           def run(): 
     3         1          3.0      3.0      7.5      a = [1]*100 
     4         1         28.0     28.0     70.0      b = [x**3 for x in a ] 
     5         1          8.0      8.0     20.0      c = [x for x in b] 
     6         1          1.0      1.0      2.5      d = c*2 

同时会在当前路径下面 生成一个名为.lprof的文件

 这个文件可以理解成刚才运行的报告的持久化的文件,可以读出来的:

root@root:/opt/pypy3.7-v7.3.2-linux64# python3 -m line_profiler tt.py.lprof
Timer unit: 1e-06 s

Total time: 4e-05 s
File: tt.py
Function: run at line 1

Line #      Hits         Time  Per Hit   % Time  Line Contents
==============================================================
     1                                           @profile 
     2                                           def run(): 
     3         1          3.0      3.0      7.5      a = [1]*100 
     4         1         28.0     28.0     70.0      b = [x**3 for x in a ] 
     5         1          8.0      8.0     20.0      c = [x for x in b] 
     6         1          1.0      1.0      2.5      d = c*2 

我们可以看到和运行的时候一样,我们发现装饰器@就能进行性能分析,是不是很方便呢

猜你喜欢

转载自blog.csdn.net/zhou_438/article/details/109183237
今日推荐