Python如何给你的程序做性能测试


Posted in Python onJuly 29, 2020

问题

你想测试你的程序运行所花费的时间并做性能测试。

解决方案

如果你只是简单的想测试下你的程序整体花费的时间, 通常使用Unix时间函数就行了,比如:

bash % time python3 someprogram.py
real 0m13.937s
user 0m12.162s
sys 0m0.098s
bash %

如果你还需要一个程序各个细节的详细报告,可以使用 cProfile 模块:

bash % python3 -m cProfile someprogram.py
     859647 function calls in 16.016 CPU seconds

  Ordered by: standard name

  ncalls tottime percall cumtime percall filename:lineno(function)
  263169  0.080  0.000  0.080  0.000 someprogram.py:16(frange)
   513  0.001  0.000  0.002  0.000 someprogram.py:30(generate_mandel)
  262656  0.194  0.000  15.295  0.000 someprogram.py:32(<genexpr>)
    1  0.036  0.036  16.077  16.077 someprogram.py:4(<module>)
  262144  15.021  0.000  15.021  0.000 someprogram.py:4(in_mandelbrot)
    1  0.000  0.000  0.000  0.000 os.py:746(urandom)
    1  0.000  0.000  0.000  0.000 png.py:1056(_readable)
    1  0.000  0.000  0.000  0.000 png.py:1073(Reader)
    1  0.227  0.227  0.438  0.438 png.py:163(<module>)
   512  0.010  0.000  0.010  0.000 png.py:200(group)
  ...
bash %

不过通常情况是介于这两个极端之间。比如你已经知道代码运行时在少数几个函数中花费了绝大部分时间。 对于这些函数的性能测试,可以使用一个简单的装饰器:

# timethis.py

import time
from functools import wraps

def timethis(func):
  @wraps(func)
  def wrapper(*args, **kwargs):
    start = time.perf_counter()
    r = func(*args, **kwargs)
    end = time.perf_counter()
    print('{}.{} : {}'.format(func.__module__, func.__name__, end - start))
    return r
  return wrapper

要使用这个装饰器,只需要将其放置在你要进行性能测试的函数定义前即可,比如:

>>> @timethis
... def countdown(n):
...   while n > 0:
...       n -= 1
...
>>> countdown(10000000)
__main__.countdown : 0.803001880645752
>>>

要测试某个代码块运行时间,你可以定义一个上下文管理器,例如:

from contextlib import contextmanager

@contextmanager
def timeblock(label):
  start = time.perf_counter()
  try:
    yield
  finally:
    end = time.perf_counter()
    print('{} : {}'.format(label, end - start))

下面是使用这个上下文管理器的例子:

>>> with timeblock('counting'):
...   n = 10000000
...   while n > 0:
...       n -= 1
...
counting : 1.5551159381866455
>>>

对于测试很小的代码片段运行性能,使用 timeit 模块会很方便,例如:

>>> from timeit import timeit
>>> timeit('math.sqrt(2)', 'import math')
0.1432319980012835
>>> timeit('sqrt(2)', 'from math import sqrt')
0.10836604500218527
>>>

timeit 会执行第一个参数中语句100万次并计算运行时间。 第二个参数是运行测试之前配置环境。如果你想改变循环执行次数, 可以像下面这样设置 number 参数的值:

>>> timeit('math.sqrt(2)', 'import math', number=10000000)
1.434852126003534
>>> timeit('sqrt(2)', 'from math import sqrt', number=10000000)
1.0270336690009572
>>>

讨论

当执行性能测试的时候,需要注意的是你获取的结果都是近似值。 time.perf_counter() 函数会在给定平台上获取最高精度的计时值。 不过,它仍然还是基于时钟时间,很多因素会影响到它的精确度,比如机器负载。 如果你对于执行时间更感兴趣,使用 time.process_time() 来代替它。例如:

from functools import wraps
def timethis(func):
  @wraps(func)
  def wrapper(*args, **kwargs):
    start = time.process_time()
    r = func(*args, **kwargs)
    end = time.process_time()
    print('{}.{} : {}'.format(func.__module__, func.__name__, end - start))
    return r
  return wrapper

最后,如果你想进行更深入的性能分析,那么你需要详细阅读 time 、timeit 和其他相关模块的文档。 这样你可以理解和平台相关的差异以及一些其他陷阱。 还可以参考13.13小节中相关的一个创建计时器类的例子。

以上就是Python如何给你的程序做性能测试的详细内容,更多关于Python做性能测试的资料请关注三水点靠木其它相关文章!

Python 相关文章推荐
python中使用mysql数据库详细介绍
Mar 27 Python
Python 常用的安装Module方式汇总
May 06 Python
python简单线程和协程学习心得(分享)
Jun 14 Python
python实现12306抢票及自动邮件发送提醒付款功能
Mar 08 Python
python多线程扫描端口(线程池)
Sep 04 Python
Python发送邮件的实例代码讲解
Oct 16 Python
Python大数据之使用lxml库解析html网页文件示例
Nov 16 Python
Django2 连接MySQL及model测试实例分析
Dec 10 Python
python开发实例之python使用Websocket库开发简单聊天工具实例详解(python+Websocket+JS)
Mar 18 Python
python编写softmax函数、交叉熵函数实例
Jun 11 Python
Python中zipfile压缩文件模块的基本使用教程
Jun 14 Python
在python中对于bool布尔值的取反操作
Dec 11 Python
Python3爬虫中关于中文分词的详解
Jul 29 #Python
Python3爬虫中pyspider的安装步骤
Jul 29 #Python
关于Python3爬虫利器Appium的安装步骤
Jul 29 #Python
Python3爬虫mitmproxy的安装步骤
Jul 29 #Python
Python使用jpype模块调用jar包过程解析
Jul 29 #Python
Python 防止死锁的方法
Jul 29 #Python
Python定义一个Actor任务
Jul 29 #Python
You might like
从C/C++迁移到PHP——判断字符类型的函数
2006/10/09 PHP
支持中文字母数字、自定义字体php验证码代码
2012/02/27 PHP
PHP获取网址的顶级域名函数代码
2012/09/24 PHP
php笔记之:php函数range() round()和list()的使用说明
2013/04/26 PHP
php+redis实现商城秒杀功能
2020/11/19 PHP
JQuery 常用方法和事件详细介绍
2013/04/18 Javascript
JavaScript—window对象使用示例
2013/12/09 Javascript
instanceof和typeof运算符的区别详解
2014/01/06 Javascript
调试代码导致IE出错的避免方法
2014/04/04 Javascript
JQuery异步获取返回值中文乱码的解决方法
2015/01/29 Javascript
3种不同的ContextMenu右键菜单实现代码
2016/11/03 Javascript
vue构建单页面应用实战
2017/04/10 Javascript
使用angular帮你实现拖拽的示例
2017/07/05 Javascript
关于vue.js组件数据流的问题
2017/07/26 Javascript
Vue打包后出现一些map文件的解决方法
2018/02/13 Javascript
深入理解Vue nextTick 机制
2018/04/28 Javascript
基于vue中对鼠标划过事件的处理方式详解
2018/08/22 Javascript
对angularJs中controller控制器scope父子集作用域的实例讲解
2018/10/08 Javascript
angular4自定义组件非input元素实现ngModel双向数据绑定的方法
2018/12/28 Javascript
JavaScript设计模式之享元模式实例详解
2019/01/17 Javascript
关于Python中异常(Exception)的汇总
2017/01/18 Python
Python:type、object、class与内置类型实例
2019/12/25 Python
python 视频下载神器(you-get)的具体使用
2021/01/06 Python
Python读取pdf表格写入excel的方法
2021/01/22 Python
基于css3实现漂亮便签样式
2013/03/18 HTML / CSS
阻止移动设备(手机、pad)浏览器双击放大网页的方法
2014/06/03 HTML / CSS
韩国流行时尚女装网站:Dintchina(中文)
2018/07/19 全球购物
荷兰天然和有机产品网上商城:BigGreenSmile.nl
2020/07/26 全球购物
英国儿童设计师服装和玩具购物网站:Zac & Lulu
2020/10/19 全球购物
财务总监管理岗位职责
2014/03/08 职场文书
办公楼租房协议书范本
2014/11/25 职场文书
同事欢送会致辞
2015/07/31 职场文书
MySQL root密码的重置方法
2021/04/21 MySQL
react如何快速设置文件路径别名
2021/04/28 Javascript
mysql在项目中怎么选事务隔离级别
2021/05/25 MySQL
Redis安装使用RedisJSON模块的方法
2022/03/23 Redis