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删除指定类型(或非指定)的文件实例详解
Jul 06 Python
举例讲解Python中的死锁、可重入锁和互斥锁
Nov 05 Python
Python迭代和迭代器详解
Nov 10 Python
Python函数any()和all()的用法及区别介绍
Sep 14 Python
python感知机实现代码
Jan 18 Python
Python自动化之数据驱动让你的脚本简洁10倍【推荐】
Jun 04 Python
pytorch中的卷积和池化计算方式详解
Jan 03 Python
基于keras输出中间层结果的2种实现方式
Jan 24 Python
Python爬虫requests库多种用法实例
May 28 Python
Python切片列表字符串如何实现切换
Aug 06 Python
Django debug为True时,css加载失败的解决方案
Apr 24 Python
Selenium浏览器自动化如何上传文件
Apr 06 Python
Python字符串对齐方法使用(ljust()、rjust()和center())
Apr 26 #Python
python如何进行基准测试
Apr 26 #Python
python实现简单的名片管理系统
Python实战之实现康威生命游戏
Python 制作自动化翻译工具
教你用Python写一个植物大战僵尸小游戏
python爬取新闻门户网站的示例
Apr 25 #Python
You might like
剧场版动画《PSYCHO-PASS 3 FIRST INSPECTOR》3月27日日本上映!
2020/03/06 日漫
PHP设计模式之工厂模式实例总结
2017/09/01 PHP
asp.net和php的区别点总结
2019/10/10 PHP
Jquery replace 字符替换实现代码
2010/12/02 Javascript
JS截取字符串常用方法整理及使用示例
2013/10/18 Javascript
jQuery 取值、赋值的基本方法整理
2014/03/31 Javascript
jQuery插件Skippr实现焦点图幻灯片特效
2015/04/12 Javascript
如何使用HTML5地理位置定位功能
2015/04/27 Javascript
jquery实现模拟百分比进度条渐变效果代码
2015/10/29 Javascript
分享一些常用的jQuery动画事件和动画函数
2015/11/27 Javascript
JS判断字符串字节数并截取长度的方法
2016/03/05 Javascript
jQuery实现布局高宽自适应的简单实例
2016/05/28 Javascript
微信小程序  http请求封装详解及实例代码
2017/02/15 Javascript
微信小程序商城项目之购物数量加减(3)
2017/04/17 Javascript
深究AngularJS如何获取input的焦点(自定义指令)
2017/06/12 Javascript
animate.css在vue项目中的使用教程
2018/08/05 Javascript
LayUI表格批量删除方法
2018/08/15 Javascript
关于微信公众号开发无法支付的问题解决
2018/12/28 Javascript
bootstrap中的导航条实例代码详解
2019/05/20 Javascript
nodejs脚本centos开机启动实操方法
2020/03/04 NodeJs
jQuery 实现DOM元素拖拽交换位置的实例代码
2020/07/14 jQuery
[07:39]第一届亚洲邀请赛回顾视频
2017/02/14 DOTA
Python中__init__和__new__的区别详解
2014/07/09 Python
Python使用min、max函数查找二维数据矩阵中最小、最大值的方法
2018/05/15 Python
java判断三位数的实例讲解
2019/06/10 Python
python re模块匹配贪婪和非贪婪模式详解
2020/02/11 Python
利用SVG和CSS3来实现一个炫酷的边框动画
2015/07/22 HTML / CSS
关于HTML5 Placeholder新标签低版本浏览器下不兼容的问题分析及解决办法
2016/01/27 HTML / CSS
澳大利亚汽车零部件、音响及配件超市:Automotive Superstore
2018/06/19 全球购物
《雨点》教学反思
2014/02/12 职场文书
团队精神口号
2014/06/06 职场文书
法英专业大学生职业生涯规划范文:衡外情,量己力!
2014/09/23 职场文书
大学生党员个人剖析材料
2014/10/08 职场文书
党员评议个人总结
2014/10/20 职场文书
基层干部个人对照检查及整改措施
2014/10/28 职场文书
入党介绍人意见范文
2015/06/01 职场文书