python如何做代码性能分析


Posted in Python onApril 26, 2021

上一篇文章我们介绍了基准测试,通过基准测试可以发现程序变慢了,那么是因为什么原因导致性能变慢的,需要进一步做代码性能分析。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 代码性能分析的资料请关注三水点靠木其它相关文章!

Python 相关文章推荐
python实现根据用户输入从电影网站获取影片信息的方法
Apr 07 Python
python定时器(Timer)用法简单实例
Jun 04 Python
python logging日志模块以及多进程日志详解
Apr 18 Python
使用Python抓取豆瓣影评数据的方法
Oct 17 Python
Python 一句话生成字母表的方法
Jan 02 Python
python 含子图的gif生成时内存溢出的方法
Jul 07 Python
Python爬取智联招聘数据分析师岗位相关信息的方法
Aug 13 Python
用Python解数独的方法示例
Oct 24 Python
python 实现图片上传接口开发 并生成可以访问的图片url
Dec 18 Python
Pytorch 的损失函数Loss function使用详解
Jan 02 Python
Django框架请求生命周期实现原理
Nov 13 Python
python 实现图片特效处理
Apr 03 Python
Python字符串对齐方法使用(ljust()、rjust()和center())
Apr 26 #Python
python如何进行基准测试
Apr 26 #Python
python实现简单的名片管理系统
Python实战之实现康威生命游戏
Python 制作自动化翻译工具
教你用Python写一个植物大战僵尸小游戏
python爬取新闻门户网站的示例
Apr 25 #Python
You might like
模仿OSO的论坛(一)
2006/10/09 PHP
PHP开源开发框架ZendFramework使用中常见问题说明及解决方案
2014/06/12 PHP
微信获取用户地理位置信息的原理与步骤
2015/11/12 PHP
PHP实现将优酷土豆腾讯视频html地址转换成flash swf地址的方法
2017/08/04 PHP
什么是PHP7中的孤儿进程与僵尸进程
2019/04/14 PHP
javascript判断单选框或复选框是否选中方法集锦
2007/04/04 Javascript
javascript 面向对象编程 聊聊对象的事
2009/09/17 Javascript
JavaScript.The.Good.Parts阅读笔记(二)作用域&amp;闭包&amp;减缓全局空间污染
2010/11/16 Javascript
window.event快达到全浏览器支持了,以后使用就方便了
2011/11/30 Javascript
javascript 中String.match()与RegExp.exec()的区别说明
2013/01/10 Javascript
Nodejs Stream 数据流使用手册
2016/04/17 NodeJs
每日十条JavaScript经验技巧(二)
2016/06/23 Javascript
详细谈谈AngularJS的子级作用域问题
2016/09/05 Javascript
JS及JQuery对Html内容编码,Html转义
2017/02/17 Javascript
用vue的双向绑定简单实现一个todo-list的示例代码
2017/08/03 Javascript
Angular 开发学习之Angular CLI的安装使用
2017/12/31 Javascript
jQuery实现的简单手风琴效果示例
2018/08/29 jQuery
Vue 组件注册实例详解
2019/02/23 Javascript
vue router 用户登陆功能的实例代码
2019/04/24 Javascript
微信小程序登陆注册功能的实现代码
2019/12/10 Javascript
浅析JavaScript 函数柯里化
2020/09/08 Javascript
Python素数检测的方法
2015/05/11 Python
Python实现完整的事务操作示例
2017/06/20 Python
Python中的is和==比较两个对象的两种方法
2017/09/06 Python
python中Switch/Case实现的示例代码
2017/11/09 Python
python查看列的唯一值方法
2018/07/17 Python
Python使用gRPC传输协议教程
2018/10/16 Python
Python编写打字训练小程序
2019/09/26 Python
解决tensorboard多个events文件显示紊乱的问题
2020/02/15 Python
.NET方向面试题
2014/11/20 面试题
EJB2和EJB3在架构上的不同点
2014/09/29 面试题
工程索赔意向书
2014/08/30 职场文书
2014办公室副主任四风对照检查材料思想汇报
2014/09/20 职场文书
会计求职自荐信范文
2015/03/04 职场文书
2015年法制宣传月活动总结
2015/03/26 职场文书
Redis高并发防止秒杀超卖实战源码解决方案
2021/11/01 Redis