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中关键字is与==的区别简述
Jul 31 Python
如何解决django配置settings时遇到Could not import settings 'conf.local'
Nov 18 Python
Scrapy爬虫实例讲解_校花网
Oct 23 Python
python生成excel的实例代码
Nov 08 Python
python控制nao机器人身体动作实例详解
Apr 29 Python
python中数组和矩阵乘法及使用总结(推荐)
May 18 Python
python通过TimedRotatingFileHandler按时间切割日志
Jul 17 Python
python实现将文件夹内的每张图片批量分割成多张
Jul 22 Python
pygame实现成语填空游戏
Oct 29 Python
创建Shapefile文件并写入数据的例子
Nov 26 Python
python中property和setter装饰器用法
Dec 19 Python
Python并发concurrent.futures和asyncio实例
May 04 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多文件上传功能实现原理及代码
2013/04/18 PHP
php数组函数array_walk用法示例
2016/05/26 PHP
Netbeans 8.2与PHP相关的新特性介绍
2016/10/08 PHP
php 根据自增id创建唯一编号类
2017/04/06 PHP
PHP-FPM的配置与优化讲解
2019/03/15 PHP
捕获关闭窗口的脚本
2009/01/10 Javascript
使用自定义setTimeout和setInterval使之可以传递参数和对象参数
2009/04/24 Javascript
菜鸟javascript基础资料整理2
2010/12/06 Javascript
jQuery $.data()方法使用注意细节
2012/12/31 Javascript
JavaScript基础知识学习笔记
2014/12/02 Javascript
JavaScript获得表单target属性的方法
2015/04/02 Javascript
举例详解Python中smtplib模块处理电子邮件的使用
2015/06/24 Javascript
jQuery+CSS实现一个侧滑导航菜单代码
2016/05/09 Javascript
分析JS中this引发的bug
2017/12/12 Javascript
微信小程使用swiper组件实现图片轮播切换显示功能【附源码下载】
2017/12/12 Javascript
JS实现的DOM插入节点操作示例
2018/04/04 Javascript
微信小程序scroll-view实现滚动穿透和阻止滚动的方法
2018/08/20 Javascript
Vue 使用Props属性实现父子组件的动态传值详解
2019/11/13 Javascript
使用python BeautifulSoup库抓取58手机维修信息
2013/11/21 Python
详解 Python中LEGB和闭包及装饰器
2017/08/03 Python
Python跨文件全局变量的实现方法示例
2017/12/10 Python
Python从Excel中读取日期一列的方法
2018/11/28 Python
使用Python爬虫库requests发送表单数据和JSON数据
2020/01/25 Python
Python并发concurrent.futures和asyncio实例
2020/05/04 Python
Manuka Doctor美国官网:麦卢卡蜂蜜和蜂毒护肤
2016/12/25 全球购物
味多美官网:蛋糕订购,100%使用天然奶油
2017/11/10 全球购物
生产部岗位职责范文
2014/02/07 职场文书
医院党的群众路线教育实践活动领导班子对照检查材料
2014/09/25 职场文书
授权委托书怎么写
2014/09/25 职场文书
公安局班子个人对照检查材料思想汇报
2014/10/09 职场文书
2015年世界卫生日活动总结
2015/02/09 职场文书
2015年监理个人工作总结
2015/05/23 职场文书
毕业典礼主持词
2015/06/29 职场文书
清明扫墓感想
2015/08/11 职场文书
Go 实现英尺和米的简单单位换算方式
2021/04/29 Golang
JS实现刷新网页后之前浏览位置保持不变示例详解
2022/08/14 Javascript