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 相关文章推荐
打开电脑上的QQ的python代码
Feb 10 Python
python学习笔记之调用eval函数出现invalid syntax错误问题
Oct 18 Python
Python实现简单文本字符串处理的方法
Jan 22 Python
使用pandas read_table读取csv文件的方法
Jul 04 Python
分享Python切分字符串的一个不错方法
Dec 14 Python
python定时复制远程文件夹中所有文件
Apr 30 Python
Django3.0 异步通信初体验(小结)
Dec 04 Python
python装饰器的特性原理详解
Dec 25 Python
Python Socket TCP双端聊天功能实现过程详解
Jun 15 Python
python利用递归方法实现求集合的幂集
Sep 07 Python
Pandas的数据过滤实现
Jan 15 Python
深度学习小工程练习之垃圾分类详解
Apr 14 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开发框架Laravel数据库操作方法总结
2014/09/03 PHP
用 Composer构建自己的 PHP 框架之设计 MVC
2014/10/30 PHP
PHP数组函数知识汇总
2016/05/12 PHP
示例详解Laravel重置密码代码重构
2016/08/10 PHP
php中输出json对象的值(实现方法)
2018/03/07 PHP
JS实现根据当前文字选择返回被选中的文字
2014/05/21 Javascript
用JavaScript实现PHP的urlencode与urldecode函数
2015/08/13 Javascript
html5+javascript实现简单上传的注意细节
2016/04/18 Javascript
JavaScript获取键盘按键的键码(参照表)
2017/01/10 Javascript
JS闭包用法实例分析
2017/03/27 Javascript
关于页面刷新vuex数据消失问题解决方案
2017/07/03 Javascript
Vue AST源码解析第一篇
2017/07/19 Javascript
Node.js 基础教程之全局对象
2017/08/06 Javascript
Angularjs中ng-repeat的简单实例
2017/08/25 Javascript
JavaScript 中的 this 工作原理
2018/06/20 Javascript
如何在项目中使用log4.js的方法步骤
2019/07/16 Javascript
JS实现动态倒计时功能(天数、时、分、秒)
2019/12/12 Javascript
详解Python的collections模块中的deque双端队列结构
2016/07/07 Python
django用户注册、登录、注销和用户扩展的示例
2018/03/19 Python
Python中循环引用(import)失败的解决方法
2018/04/22 Python
使用python编写udp协议的ping程序方法
2018/04/22 Python
详解Python数据可视化编程 - 词云生成并保存(jieba+WordCloud)
2019/03/26 Python
Opencv-Python图像透视变换cv2.warpPerspective的示例
2019/04/11 Python
使用PYTHON解析Wireshark的PCAP文件方法
2019/07/23 Python
pygame库实现俄罗斯方块小游戏
2019/10/29 Python
Django连接数据库并实现读写分离过程解析
2019/11/13 Python
Django import export实现数据库导入导出方式
2020/04/03 Python
高级人员简历的自我评价分享
2013/11/03 职场文书
校园十大歌手策划书
2014/02/01 职场文书
街道务虚会发言材料
2014/10/20 职场文书
婚礼上证婚人致辞
2015/07/28 职场文书
新学期新寄语,献给新生们!
2019/11/15 职场文书
如何用Laravel包含你自己的帮助函数
2021/05/27 PHP
Canvas如何做个雪花屏版404的实现
2021/09/25 HTML / CSS
世界十大儿童漫画书排名,法国国宝漫画排第五,第二是轰动日本连环
2022/03/18 欧美动漫
多人盗宝《绿林侠盗》第三赛季4.5上线 跨平台实装
2022/04/03 其他游戏