python如何做代码性能分析

上一篇文章我们介绍了基准测试,通过基准测试可以发现程序变慢了,那么是因为什么原因导致性能变慢的,需要进一步做代码性能分析。python同样提供了性能分析工具。

cProfile

cProfile是python默认的性能分析器,他只测量CPU时间,并不关心内存消耗和其他与内存相关联的信息。

from time import sleep
import random

def random_list(start, end, length):
    """
    生成随机列表
    :param start: 随机开始数
    :param end: 随机结束数
    :param length: 列表长度
    """
    data_list = []
    for i in range(length):
        data_list.append(random.randint(start, end))
    return data_list

def bubble_sort(arr):
    """
    冒泡排序: 对列表进行排序
    :param arr 列表
    """
    n = len(arr)
    sleep(1)
    for i in range(n):
        for j in range(0, n - i - 1):
            if arr[j] > arr[j + 1]:
                arr[j], arr[j + 1] = arr[j + 1], arr[j]
    return arr

if __name__ == '__main__':
    get_data_list = random_list(1, 99, 10)

    import cProfile
    cProfile.run('bubble_sort({})'.format(get_data_list))

继续使用上一篇文章中的例子,引用cProfile模块,run()方法参数说明。

run(statement, filename=None, sort=-1)

  • statement: 需要测试的代码或者函数(函数名)
  • fielname: 结果保存的位置, 默认为stdout
  • sort: 结果排序方法,常用的有cumtime: 累积时间, name: 函数名, line: 行号

为了使结果统计出耗时部分,我们加了sleep,结果如下:

❯ python demo.py
         6 function calls in 1.004 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000    1.004    1.004 <string>:1(<module>)
        1    0.000    0.000    1.004    1.004 demo.py:19(bubble_sort)
        1    0.000    0.000    1.004    1.004 {built-in method builtins.exec}
        1    0.000    0.000    0.000    0.000 {built-in method builtins.len}
        1    1.004    1.004    1.004    1.004 {built-in method time.sleep}
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}
  • 6 function calls in 1.004 seconds 6个函数调用被监控,耗时1.004秒。
  • ncalls 函数被调用的次数。如果这一列有两个值,就表示有递归调用,第二个值是原生调用次数,第一个值是总调用次数。
  • tottime 函数内部消耗的总时间。(可以帮助优化)
  • percall 是tottime除以ncalls,一个函数每次调用平均消耗时间。
  • cumtime 之前所有子函数消费时间的累计和。
  • filename:lineno(function) 被分析函数所在文件名、行号、函数名。

line_profiler

line_profiler 可以提供有关时间是如何在各行之间分配的信息,直白一点就是给出程序每行的耗时,在无法确定哪行语句最浪费时间,这很有用。

line_profiler是一个第三方模块,需要安装。

https://github.com/pyutils/line_profiler

from time import sleep
import random

def random_list(start, end, length):
    """
    生成随机列表
    :param start: 随机开始数
    :param end: 随机结束数
    :param length: 列表长度
    """
    data_list = []
    for i in range(length):
        data_list.append(random.randint(start, end))
    return data_list

@profile
def bubble_sort(arr):
    """
    冒泡排序: 对列表进行排序
    :param arr 列表
    """
    n = len(arr)
    sleep(1)
    for i in range(n):
        for j in range(0, n - i - 1):
            if arr[j] > arr[j + 1]:
                arr[j], arr[j + 1] = arr[j + 1], arr[j]
    return arr

if __name__ == '__main__':
    get_data_list = random_list(1, 99, 10)
    bubble_sort(get_data_list)

给需要监控的函数加上@profile 装饰器。通过kernprof命令运行文件(安装完line_profiler生成的命令)。

参数说明:

  • -l:以使用函数line_profiler
  • -v:以立即将结果打印到屏幕

运行结果:

kernprof -l -v demo.py
Wrote profile results to demo.py.lprof
Timer unit: 1e-06 s

Total time: 1.00416 s
File: demo.py
Function: bubble_sort at line 18

Line #      Hits         Time  Per Hit   % Time  Line Contents
==============================================================
    18                                           @profile
    19                                           def bubble_sort(arr):
    20                                               """
    21                                               冒泡排序: 对列表进行排序
    22                                               :param arr 列表
    23                                               """
    24         1          8.0      8.0      0.0      n = len(arr)
    25         1    1004030.0 1004030.0    100.0      sleep(1)
    26        11         15.0      1.4      0.0      for i in range(n):
    27        55         44.0      0.8      0.0          for j in range(0, n - i - 1):
    28        45         41.0      0.9      0.0              if arr[j] > arr[j + 1]:
    29        20         21.0      1.1      0.0                  arr[j], arr[j + 1] = arr[j + 1], arr[j]
    30         1          1.0      1.0      0.0      return arr

输出非常直观,分成了6列。

  • Line #:运行的代码行号。
  • Hits:代码行运行的次数。
  • Time:代码行的执行时间,单位为微秒。
  • Per Hit:Time/Hits。
  • % Time:代码行总执行时间所占的百分比。
  • Line Contents:代码行的内容。

只需查看% Time列,就可清楚地知道时间都花在了什么地方。

总结

性能测试分析站在项目层面是一个很庞大的话题,以前为测试工程师,关注的是性能工具的使用,以及用户维度的性能[1];作为开发工程师,每个功能都是由一个个函数/方法组成,我们去分析每个函数/方法,甚至是每行代码的耗时,才能更好的进行代码层面的性能优化。

以上就是python如何做代码性能分析的详细内容,更多关于python 代码性能分析的资料请关注我们其它相关文章!

(0)

相关推荐

  • python中delattr删除对象方法的代码分析

    最近我们针对对象属性这块,介绍了不少关于测试属性的方法.在进行一系列测试后,我们发现这个属性并不需要,这时候就要用到删除的功能.在python中可以选择delattr函数删除对象的属性,基于它的删除功能,是否能扩展到删除的对象的方法上,在我们对delattr函数进行全面了解后,展开实例的测试. 1.说明 函数作用用来删除指定对象的指定名称的属性,和setattr函数作用相反. 不能删除对象的方法. 2.参数 object -- 对象. name -- 必须是对象的属性. 3.返回值 无. 4.实

  • Python爬虫分析微博热搜关键词的实现代码

    1,使用到的第三方库 requests BeautifulSoup 美味汤 worldcloud 词云 jieba 中文分词 matplotlib 绘图 2,代码实现部分 import requests import wordcloud import jieba from bs4 import BeautifulSoup from matplotlib import pyplot as plt from pylab import mpl #设置字体 mpl.rcParams['font.sans

  • Python内置类型性能分析过程实例

    这篇文章主要介绍了Python内置类型性能分析过程实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 timeit模块 timeit模块可以用来测试一小段Python代码的执行速度. Timer是测量小段代码执行速度的类. class timeit.Timer(stmt='pass', setup='pass', timer=<timer function>) stmt参数是要测试的代码语句(statment): setup参数是运行代码时需

  • python一些性能分析的技巧

    当我们开始精通编程语言时,我们不仅希望实现最终目标,而且希望使我们的程序高效. 在这个教程中,我们将学习一些Ipython的命令,这些命令可以帮助我们对Python代码进行时间分析. 注意,在本教程中,我建议使用Anaconda. 1.分析一行代码 要检查一行python代码的执行时间,请使用 %timeit .下面是一个简单的例子来了解它的工作原理: #### magics命令%timeit的简单用法 %timeit [num for num in range(20)] #### 输出 1.0

  • Python中判断子串存在的性能比较及分析总结

    起步 对于子串搜索,Python提供了多种实现方式:in, find, index, __contains__,对其进行性能比较: import timeit def in_(s, other): return other in s def contains(s, other): return s.__contains__(other) def find(s, other): return s.find(other) != -1 def index(s, other): try: s.index

  • cProfile Python性能分析工具使用详解

    前言 Python自带了几个性能分析的模块:profile.cProfile和hotshot,使用方法基本都差不多,无非模块是纯Python还是用C写的.本文介绍cProfile. 例子 import time def func1(): sum = 0 for i in range(1000000): sum += i def func2(): time.sleep(10) func1() func2() 运行 python -m cProfile del.py 运行结果 结果分析 执行了6个函

  • 使用pycallgraph分析python代码函数调用流程以及框架解析

    技术背景 在上一篇博客中,我们介绍了使用量子计算模拟器ProjectQ去生成一个随机数,也介绍了随机数的应用场景等.但是有些时候我们希望可以打开这里面实现的原理,去看看在产生随机数的过程中经历了哪些运算,调用了哪些模块.只有梳理清楚这些相关的内容,我们才能够更好的使用这个产生随机数的功能.这里我们就引入一个工具pycallgraph,可以根据执行的代码,给出这些代码背后所封装和调用的所有函数.类的关系图,让我们一起来了解下这个工具的安装和使用方法. Manjaro Linux平台安装graphv

  • 使用bandit对目标python代码进行安全函数扫描的案例分析

    技术背景 在一些对python开源库代码的安全扫描中,我们有可能需要分析库中所使用到的函数是否会对代码的执行环境造成一些非预期的影响.典型的例如python的沙箱逃逸问题,通过一些python的第三方库可以执行系统shell命令,而这就不在python的沙箱防护范围之内了.关于python的沙箱逃逸问题,这里不作展开,这也是困扰业界多年的一个问题,连python官方也提过python的沙箱是没有完美的防护方案的,这里仅作为一个背景案例使用: # subprocess_Popen.py impor

  • python3中确保枚举值代码分析

    有的小伙伴对于枚举的理解很模糊,其实我们可以把它看成一个数量的大管家,对其中的每一个数进行检查,保证里面的数字都没有重复的,这就是枚举的用法.相信听完小编的解释,小伙伴们已经可以结合理解了枚举的定义.今天我们主要教大家用代码来在python3中确保枚举值,具体的操作方法我们继续往下看. 创建 枚举语法与 class 语法相同,枚举的定义可以通过继承 Enum 的方式来实现, 看一下示例: from enum import Enum class WeekDay(Enum): Mon = 0 Tue

  • Python性能分析工具Profile使用实例

    这篇文章主要介绍了Python性能分析工具Profile使用实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 代码优化的前提是需要了解性能瓶颈在什么地方,程序运行的主要时间是消耗在哪里,对于比较复杂的代码可以借助一些工具来定位,python 内置了丰富的性能分析工具,如 profile,cProfile 与 hotshot 等.其中 Profiler 是 python 自带的一组程序,能够描述程序运行时候的性能,并提供各种统计帮助用户定位程序

  • Python性能分析工具py-spy原理用法解析

    Py-Spy介绍 引用官方的介绍: Py-Spy是Python程序的抽样分析器. 它允许您可视化查看Python程序在哪些地方花了更多时间,整个监控方式无需重新启动程序或以任何方式修改工程代码. Py-Spy的开销非常低:它是用Rust编写的,速度与编译的Python程序不在同一个进程中运行. 这意味着Py-Spy可以安全地用于生成生产环境中的Python应用调优分析. github:https://github.com/benfred/py-spy 安装 pip install py-spy

随机推荐