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 相关文章推荐
以Flask为例讲解Python的框架的使用方法
Apr 29 Python
django接入新浪微博OAuth的方法
Jun 29 Python
numpy自动生成数组详解
Dec 15 Python
Python3实现的画图及加载图片动画效果示例
Jan 19 Python
对python遍历文件夹中的所有jpg文件的实例详解
Dec 08 Python
python执行精确的小数计算方法
Jan 21 Python
Python实现程序判断季节的代码示例
Jan 28 Python
python GUI库图形界面开发之PyQt5信号与槽的高级使用技巧装饰器信号与槽详细使用方法与实例
Mar 06 Python
Django values()和value_list()的使用
Mar 31 Python
pyspark给dataframe增加新的一列的实现示例
Apr 24 Python
Python虚拟环境的创建和使用详解
Sep 07 Python
Pytorch中使用ImageFolder读取数据集时忽略特定文件
Mar 23 Python
Python字符串对齐方法使用(ljust()、rjust()和center())
Apr 26 #Python
python如何进行基准测试
Apr 26 #Python
python实现简单的名片管理系统
Python实战之实现康威生命游戏
Python 制作自动化翻译工具
教你用Python写一个植物大战僵尸小游戏
python爬取新闻门户网站的示例
Apr 25 #Python
You might like
PHP读MYSQL中文乱码的解决方法
2006/12/17 PHP
收集的PHP中与数组相关的函数
2007/03/22 PHP
浅析PHP原理之变量分离/引用(Variables Separation)
2013/08/09 PHP
php+mysqli批量查询多张表数据的方法
2015/01/29 PHP
PHP中常用的魔术方法
2017/04/28 PHP
PHP5.6新增加的可变函数参数用法分析
2017/08/25 PHP
使用laravel根据用户类型来显示或隐藏字段
2019/10/17 PHP
javascript 异常处理使用总结
2009/06/21 Javascript
基于jquery的兼容各种浏览器的iframe自适应高度的脚本
2010/08/13 Javascript
javascript ajax 仿百度分页函数
2013/10/29 Javascript
jquery为页面增加快捷键示例
2014/01/31 Javascript
javascript删除数组元素并且数组长度减小的简单实例
2014/02/14 Javascript
javascript屏蔽右键代码
2014/05/15 Javascript
jQuery html()方法使用不了无法显示内容的问题
2014/08/06 Javascript
node.js中的fs.exists方法使用说明
2014/12/17 Javascript
jQuery实现多级下拉菜单jDropMenu的方法
2015/08/28 Javascript
vue.js表格分页示例
2016/10/18 Javascript
Easyui在treegrid添加控件的实现方法
2017/06/23 Javascript
Bootstrap一款超好用的前端框架
2017/09/25 Javascript
vue移动端下拉刷新和上拉加载的实现代码
2018/09/08 Javascript
Java Varargs 可变参数用法详解
2020/01/28 Javascript
微信小程序实现带放大效果的轮播图
2020/05/26 Javascript
[03:40]DOTA2亚洲邀请赛小组赛第二日 赛事回顾
2015/01/31 DOTA
深入理解Python 代码优化详解
2014/10/27 Python
Python中Iterator迭代器的使用杂谈
2016/06/20 Python
python解析基于xml格式的日志文件
2017/02/25 Python
基于腾讯云服务器部署微信小程序后台服务(Python+Django)
2019/05/08 Python
Numpy中ndim、shape、dtype、astype的用法详解
2020/06/14 Python
html5简单示例_动力节点Java学院整理
2017/07/07 HTML / CSS
好莱坞百老汇御用王牌美妆:Koh Gen Do 江原道
2018/04/03 全球购物
常用UNIX 命令(Linux的常用命令)
2015/12/26 面试题
软件测试题目
2013/02/27 面试题
毕业生个人求职信范文分享
2014/01/05 职场文书
常务副总经理岗位职责
2014/04/12 职场文书
2015年环卫工作总结
2015/04/28 职场文书
Python实现批量自动整理文件
2022/03/16 Python