当前位置: 首页 > news >正文

Python 高手编程系列八十八:微观分析

当找到慢速函数时,有时需要进行更多的测试工作,只测试程序的一部分。通过在速
度测试中手动检测一部分代码来完成测试。
例如,可以从装饰器使用 cProfile 模块,如下所示:

import tempfile, os, cProfile, pstats
def profile(column=‘time’, list=5):
… def _profile(function):
… def __profile(*args, **kw):
… s = tempfile.mktemp()
… profiler = cProfile.Profile()
… profiler.runcall(function,args, **kw)
… profiler.dump_stats(s)
… p = pstats.Stats(s)
… p.sort_stats(column).print_stats(list)
… return __profile
… returnprofile

from myapp import main
@profile(‘time’, 6)
… def main_profiled():
… return main()

main_profiled()
Mon Apr 4 22:01:01 2016 /tmp/tmpvswuovz

1207 function calls in 8.243 seconds
Ordered by: internal time
List reduced from 7 to 6 due to restriction <6>
Ncalls tottime percall cumtime percall file:lineno(function)
602 8.241 0.014 8.241 0.014 {built-in method sleep}
400 0.001 0.000 4.026 0.010 myapp.py:5(medium)
2 0.001 0.000 8.243 4.121 myapp.py:13(heavy)
200 0.000 0.000 0.213 0.001 myapp.py:9(light)
1 0.000 0.000 8.243 8.243 myapp.py:21(main)
1 0.000 0.000 8.243 8.243 :1(main_profiled)
from myapp import light
stats = profile()(light)
stats()
Mon Apr 4 22:01:57 2016 /tmp/tmpnp_zk7dl
3 function calls in 0.001 seconds
Ordered by: internal time
ncalls tottime percall cumtime percall file:lineno(function)
1 0.001 0.001 0.001 0.001 {built-in method sleep}
1 0.000 0.000 0.001 0.001 myapp.py:9(light)
这种方法允许测试应用程序的一部分,并锐化统计输出。但在这个阶段,有一个被调
用者列表可能不是很有用,因为已经指出该函数需要进行优化。唯一令人关注的信息是知
道它有多快,然后增强它。
timeit 提供一种简单的方法来测量小代码片段的执行时间,它使用主机系统提供的
最佳底层计时器(time.time 或 time.clock),从而更好地满足这种需要,如下所示:
from myapp import light
import timeit
t = timeit.Timer(‘main()’)
t.timeit(number=5)
10000000 loops, best of 3: 0.0269 usec per loop
10000000 loops, best of 3: 0.0268 usec per loop
10000000 loops, best of 3: 0.0269 usec per loop
10000000 loops, best of 3: 0.0268 usec per loop
10000000 loops, best of 3: 0.0269 usec per loop
5.6196951866149902
该模块可以被重复调用,并且面向测试隔离的代码片段。这在应用程序上下文之外非常有用,在命令提示符中,例如,在现有应用程序中使用不是很方便。
但是应该谨慎使用 timeit 的结果。这是一个非常好的工具,它可以客观地比较两段
短代码,但它也会让你很容易犯下危险的错误,这将导致令人困惑的结论。这里,例如,
通过 timeit 模块对两个无害的代码片段进行比较,它可以使你认为通过加法的字符串连
接比 str.join()方法更快:
$ python3 -m timeit -s ‘a = map(str, range(1000))’ ‘“”.join(a)’
1000000 loops, best of 3: 0.497 usec per loop
$ python3 -m timeit -s ‘a = map(str, range(1000)); s=“”’ ‘for i in a: s
+= i’
10000000 loops, best of 3: 0.0808 usec per loop
从第 2 章开始,我们知道通过加法连接字符串不是一个好的模式。尽管有一些针对这
种用法设计的一些较小的 CPython 微优化,它最终会导致二次的运行时间。问题在于
timeit(命令行中-s 参数)设置参数的细微差别,以及 Python 3 中的范围如何工作。我
不会讨论问题的细节,但会把它留给你作为一个练习。总之,在 Python 3 中,这是正确的
比较使用加法和 str.join()连接字符串的方法,如下所示:
$ python3 -m timeit -s ‘a = [str(i) for i in range(10000)]’ ‘s=“”.
join(a)’
10000 loops, best of 3: 128 usec per loop
$ python3 -m timeit -s ‘a = [str(i) for i in range(10000)]’ ’
s = “”
for i in a:
s += i

1000 loops, best of 3: 1.38 msec per loop
测量 Pystones
当测量执行时间时,结果取决于计算机硬件。为了能够产生通用测量,最简单的方法
测量固定序列的代码基准速度,并计算出它的比率。由此,函数所花费的时间可以转换为
一个比较通用的值,可以在任何计算机上比较。
Python 在其 test 包中提供了一个基准测试工具,用于测量一个精选的操作序列的持
续时间。结果是每秒钟计算机能够执行的 pystones 数量,在现代硬件上通常约为一秒,
如下所示:
from test import pystone
pystone.pystones()
(1.0500000000000007, 47619.047619047589)
该比率可用于将分析的持续时间转换为 pystones 的数量:
from test import pystone
benchtime, pystones = pystone.pystones()
def seconds_to_kpystones(seconds):
… return (pystones
seconds) / 1000


seconds_to_kpystones(0.03)
1.4563106796116512
seconds_to_kpystones(1)
48.543689320388381
seconds_to_kpystones(2)
97.087378640776762
seconds_to_kpystones 返回千个 ρystones 的数量。如果你想编写一些速度断言,
这个转换可以包含在你的测试中。
拥有 pystones 将允许你在测试中使用此装饰器,以便于你在执行时间上设置断言。
这些测试可以在任何计算机上运行,并让开发人员避免速度回归。当应用程序的一部分已
优化时,他们将能够在测试中设置其最大执行时间,并确保它不会被进一步的更改所破坏。
这种方法当然不是理想的并且 100%准确的,但是它至少比以硬编码的执行时间断言更好,
这些断言是以秒表示的原始值。

http://www.zskr.cn/news/1513374.html

相关文章:

  • 嵌入式Linux入门实战:基于i.MX23 EVK的硬件架构与BSP深度解析
  • 2026 东莞汽车音响改装行业标杆:虎门杰生 31 年深耕,全维度定义行业绝对天花板 - 汽车音响改装
  • Fast DDS配置避坑指南:DomainParticipant的QoS设置与Listener监听器实战详解
  • 5MB超轻量中文字体终极指南:嵌入式设备中文显示难题的完美解决方案
  • 2026论文必藏降AIGC平台大曝光:智能算法直击安全阈值
  • 别再只用nn.Linear了!用PyTorch手搓一个能‘旋转’的向量神经元层(附完整代码)
  • Python 爬虫实战:艺恩影视排行榜数据爬取与热度分析
  • 2026福州沙发翻新换皮换布上门服务哪家靠谱?推荐匠阁/御匠/锦修/框架加固处理 - 我叫一
  • 降AIGC软件红黑榜:亲测3款热门工具,剖析实用程度与常见陷阱,文末附技巧
  • 别再死记公式了!一个生活化比喻带你理解RSA共模攻击的本质
  • 手游出海买量实战:如何精准抓取同行「正在跑」的广告素材?工具选型+避坑指南
  • 知识管理系统 | 毕业设计完整源码
  • 告别线上会议杂音!手把手教你用Python+WebRTC实现音频3A降噪(附代码)
  • 摒弃摆烂心态,让四年青春锋芒尽显
  • Windows热键侦探:彻底解决快捷键冲突的终极指南
  • 阿里二面:帮我分析下我们这边RAG准确率低于95%的原因
  • VMware Workstation Pro 17 免费许可证密钥:专业级虚拟化工具完整指南
  • 2026大连沙发翻新换皮换布上门服务哪家靠谱?推荐匠阁/御匠/锦修/修复塌陷坐垫 - 我叫一
  • 外部群自动化运营的技术选型:官方 API 与 RPA 连接器对比
  • 深入解析MPC5565:汽车电子与工业控制中的Power Architecture微控制器实战
  • OpenPLC:开源工业控制的技术革命与架构突破
  • 2026年 湿毛巾厂家推荐排行榜,一次性/酒店/餐饮/独立包装湿毛巾,清洁擦手多功能源头品牌深度解析 - 品牌发掘
  • MC68HC916X1嵌入式开发:复位、中断与芯片选择三大核心机制详解
  • 为什么这个免费开源甘特图工具能彻底改变你的项目管理方式?
  • 手把手复现SIGCOMM‘14的BBA算法:用不到10行Python代码理解流媒体码率自适应的核心
  • 从游戏卡到计算卡:为什么你的RTX 4090在AI炼丹时,算力可能“虚标”?聊聊Tensor Core与FP32/FP64
  • KUKA库卡机器人Ethernet KRL通讯解析:从smartHMI调试到C#上位机数据监控全流程
  • 告别手动拼UI!用C#和Aspose.PSD库,5步实现PSD图层到Unity碎图的自动导出
  • 2026年 燃气表检定装置/音速喷嘴式燃气表检定装置十大品牌推荐:高精度与稳定性能的专业首选! - 品牌发掘
  • 用Python复现CBOE SKEW指数:一个量化新手的50ETF期权择时实战(附完整代码)