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用于url解码和中文解析的小脚本(python url decoder)
Aug 11 Python
Python生成验证码实例
Aug 21 Python
在Django中创建动态视图的教程
Jul 15 Python
Python实现多线程HTTP下载器示例
Feb 11 Python
Python中import机制详解
Nov 14 Python
用Pygal绘制直方图代码示例
Dec 07 Python
python Spyder界面无法打开的解决方法
Apr 27 Python
python导入坐标点的具体操作
May 10 Python
python多线程同步之文件读写控制
Feb 25 Python
关于Python3 类方法、静态方法新解
Aug 30 Python
python实现tail -f 功能
Jan 17 Python
python 写一个水果忍者游戏
Jan 13 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
虫族 Zerg 魔法科技
2020/03/14 星际争霸
简单的php写入数据库类代码分享
2011/07/26 PHP
PHP取余函数介绍MOD(x,y)与x%y
2014/05/15 PHP
php数组转成json格式的方法
2015/03/09 PHP
浅谈Yii乐观锁的使用及原理
2017/07/25 PHP
jQuery 数据缓存data(name, value)详解及实现
2010/01/04 Javascript
jquery解决图片路径不存在执行替换路径
2013/02/06 Javascript
JS仿百度搜索自动提示框匹配查询功能
2013/11/21 Javascript
使用pjax实现无刷新更改页面url
2015/02/05 Javascript
Javascript实现div层渐隐效果的方法
2015/05/30 Javascript
详解基于mpvue的小程序markdown适配解决方案
2018/05/08 Javascript
Js经典案例的实例代码
2018/05/10 Javascript
taro开发微信小程序的实践
2019/05/21 Javascript
ES6 Class中实现私有属性的一些方法总结
2019/07/08 Javascript
layui实现数据表格table分页功能(ajax异步)
2019/07/27 Javascript
ES6基础之 Promise 对象用法实例详解
2019/08/22 Javascript
javascript递归函数定义和用法示例分析
2020/07/22 Javascript
js实现手表表盘时钟与圆周运动
2020/09/18 Javascript
用python做一个搜索引擎(Pylucene)的实例代码
2017/07/05 Python
Python(TensorFlow框架)实现手写数字识别系统的方法
2018/05/29 Python
基于python3实现socket文件传输和校验
2018/07/28 Python
浅谈PyQt5 的帮助文档查找方法,可以查看每个类的方法
2019/06/25 Python
Django之全局使用request.user.username的实例详解
2020/05/14 Python
python中Ansible模块的Playbook的具体使用
2020/05/28 Python
多视角3D可旋转的HTML5 Logo动画
2016/03/02 HTML / CSS
宝信软件JAVA工程师面试经历
2012/08/19 面试题
大学同学聚会邀请函
2014/01/19 职场文书
安全协议书范本
2014/04/21 职场文书
车间核算员岗位职责
2014/07/01 职场文书
三方股东合作协议书范本
2014/09/28 职场文书
党的群众路线教育实践活动个人整改措施材料
2014/11/04 职场文书
2014年社区宣传工作总结
2014/12/02 职场文书
2015年度公共机构节能工作总结
2015/05/26 职场文书
Nginx中break与last的区别详析
2021/03/31 Servers
Django+Celery实现定时任务的示例
2021/06/23 Python
ssh服务器拒绝了密码 请再试一次已解决(亲测有效)
2022/08/14 Servers