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中list循环语句用法实例
Nov 10 Python
详解Python多线程
Nov 14 Python
Python实现的爬虫功能代码
Jun 24 Python
tensorflow输出权重值和偏差的方法
Feb 10 Python
Python Flask前后端Ajax交互的方法示例
Jul 31 Python
python 将json数据提取转化为txt的方法
Oct 26 Python
win7 x64系统中安装Scrapy的方法
Nov 18 Python
python调用支付宝支付接口流程
Aug 15 Python
Python模块的定义,模块的导入,__name__用法实例分析
Jan 07 Python
python GUI库图形界面开发之PyQt5信号与槽的高级使用技巧(自定义信号与槽)详解与实例
Mar 06 Python
python中return不返回值的问题解析
Jul 22 Python
Python使用海龟绘图实现贪吃蛇游戏
Jun 18 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
PHP 日志缩略名的创建函数代码
2010/05/26 PHP
PHP正则表达式之定界符和原子介绍
2012/10/05 PHP
PHP 获取文件路径(灵活应用__FILE__)
2013/02/15 PHP
yii2高级应用之自定义组件实现全局使用图片上传功能的方法
2016/10/08 PHP
jquery1.9 下检测浏览器类型和版本的方法
2013/12/26 Javascript
js+css实现的简单易用兼容好的分页
2013/12/30 Javascript
jQuery 删除/替换DOM元素的几种方式
2014/05/20 Javascript
javascript移动设备Web开发中对touch事件的封装实例
2014/06/05 Javascript
js实现iframe跨页面调用函数的方法
2014/12/13 Javascript
javascript十六进制及二进制转化的方法
2015/05/06 Javascript
Backbone.js框架中Model与Collection的使用实例
2016/05/07 Javascript
修改js confirm alert 提示框文字的简单实例
2016/06/10 Javascript
JS中对数组元素进行增删改移的方法总结
2016/12/15 Javascript
Vue axios 中提交表单数据(含上传文件)
2017/07/06 Javascript
AngularJS 控制器 controller的详解
2017/10/17 Javascript
vue.js整合vux中的上拉加载下拉刷新实例教程
2018/01/09 Javascript
深入理解node.js http模块
2018/01/24 Javascript
详解Angularjs 自定义指令中的数据绑定
2018/07/19 Javascript
vue与原生app的对接交互的方法(混合开发)
2018/11/28 Javascript
浅谈vue后台管理系统权限控制思考与实践
2018/12/19 Javascript
Jquery的autocomplete插件用法及参数讲解
2019/03/12 jQuery
Node.js中package.json中库的版本号(~和^)
2019/04/02 Javascript
浅谈bootstrap layer.open中end的使用方法
2019/09/12 Javascript
微信小程序实现上拉加载功能
2019/11/20 Javascript
python读取注册表中值的方法
2013/04/08 Python
Python基于PyGraphics包实现图片截取功能的方法
2017/12/21 Python
Python 修改列表中的元素方法
2018/06/26 Python
Python之指数与E记法的区别详解
2019/11/21 Python
关于Theano和Tensorflow多GPU使用问题
2020/06/19 Python
详解html5 postMessage解决跨域通信的问题
2018/08/17 HTML / CSS
团日活动总结
2014/04/28 职场文书
学习教师法的心得体会
2014/09/03 职场文书
出国签证在职证明
2014/09/20 职场文书
2014年部门工作总结
2014/11/12 职场文书
2015上半年个人工作总结
2015/07/27 职场文书
为Centos安装指定版本的Docker
2022/04/01 Servers