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 httplib,smtplib使用方法
Sep 06 Python
Python urlopen 使用小示例
Sep 06 Python
python模拟新浪微博登陆功能(新浪微博爬虫)
Dec 24 Python
基于python实现的抓取腾讯视频所有电影的爬虫
Apr 22 Python
Python学习pygal绘制线图代码分享
Dec 09 Python
Django 限制用户访问频率的中间件的实现
Aug 23 Python
python pillow模块使用方法详解
Aug 30 Python
Python3操作Excel文件(读写)的简单实例
Sep 02 Python
Python实现自动访问网页的例子
Feb 21 Python
django models里数据表插入数据id自增操作
Jul 15 Python
python异常中else的实例用法
Jun 15 Python
Python可视化学习之matplotlib内置单颜色
Feb 24 Python
Python字符串对齐方法使用(ljust()、rjust()和center())
Apr 26 #Python
python如何进行基准测试
Apr 26 #Python
python实现简单的名片管理系统
Python实战之实现康威生命游戏
Python 制作自动化翻译工具
教你用Python写一个植物大战僵尸小游戏
python爬取新闻门户网站的示例
Apr 25 #Python
You might like
PHP编码规范的深入探讨
2013/06/06 PHP
详解PHP变量传值赋值和引用赋值变量销毁
2019/03/23 PHP
PHP dirname简单使用代码实例
2020/11/13 PHP
Extjs学习笔记之八 继承和事件基础
2010/01/08 Javascript
jquery里的each使用方法详解
2010/12/22 Javascript
javascript模拟select,jselect的方法实现
2012/11/08 Javascript
深入了解javascript中的prototype与继承
2013/04/14 Javascript
如何用JavaScript动态呼叫函数(两种方式)
2013/05/03 Javascript
Jquery响应回车键直接提交表单操作代码
2014/07/25 Javascript
JavaScript中操作字符串小结
2015/05/04 Javascript
通过设置CSS中的position属性来固定层的位置
2015/12/14 Javascript
基于Bootstrap3表格插件和分页插件实例详解
2016/05/17 Javascript
基于JavaScript实现回到页面顶部动画代码
2016/05/24 Javascript
Javascript中indexOf()和lastIndexOf应用方法实例
2016/08/24 Javascript
浅析JavaScript的几种Math函数,random(),ceil(),round(),floor()
2016/12/22 Javascript
Vue 2.x教程之基础API
2017/03/06 Javascript
Vue实现一个返回顶部backToTop组件
2017/07/25 Javascript
vue.js路由跳转详解
2017/08/28 Javascript
利用10行js代码实现上下滚动公告效果
2017/12/08 Javascript
基于cropper.js封装vue实现在线图片裁剪组件功能
2018/03/01 Javascript
JS实现点击拉拽轮播图pc端移动端适配
2018/09/05 Javascript
详解如何用VUE写一个多用模态框组件模版
2018/09/27 Javascript
Python实现爬虫抓取与读写、追加到excel文件操作示例
2018/06/27 Python
Python之pymysql的使用小结
2019/07/01 Python
python爬虫 模拟登录人人网过程解析
2019/07/31 Python
对python中的装包与解包实例详解
2019/08/24 Python
windows 10 设定计划任务自动执行 python 脚本的方法
2019/09/11 Python
使用pandas实现连续数据的离散化处理方式(分箱操作)
2019/11/22 Python
Python爬取腾讯视频评论的思路详解
2019/12/19 Python
keras 读取多标签图像数据方式
2020/06/12 Python
收银出纳员岗位职责
2014/02/23 职场文书
运输企业安全生产责任书
2014/07/28 职场文书
党员批评与自我批评思想汇报(集锦)
2014/09/14 职场文书
群众路线对照检查材料思想汇报怎么写
2014/09/18 职场文书
go 原生http web 服务跨域restful api的写法介绍
2021/04/27 Golang
JavaScript数组 几个常用方法总结
2021/11/11 Javascript