C++后端团队对我们产品的性能非常敏感。 今天,我将向大家概述我们如何定义“产品的性能”以及衡量它的方法。 在此过程中,我希望向您介绍一些新的想法,您可以用来测试您的产品的性能以及。你可以在上阅读亚历克斯·萨曼的博客文章 “如何测试编译器后端” 关于编译器测试的一些背景知识。 此外,你可以在上阅读Asmaa Taha的博客文章 VCBench,我们的性能测试自动化系统 .
先问后答
在开始衡量产品性能之前,您应该回答以下几个问题:
· 客户需要我的产品具备哪些功能?
· 我可以运行哪些场景来可靠地度量性能?
· 我可以衡量哪些指标来产生可操作的结果?
· 如何执行测试以最小化可变性?
选择要测量的特征
了解客户需求是确定他们需要执行哪些功能领域的第一步。 我们确定性能场景的一些途径包括:
· 通过会议、调查、博客等与客户交谈。
· 你报告的连接错误(注意连接错误)
· 来自微软内部团队的反馈
· 常见的历史性能错误报告
基于这些数据,我们将Visual C++编译器的性能分解为三个方面:
· 编译程序 吞吐量 –用一组编译器参数编译一组源代码的秒数
o 对于那些必须等待构建完成的客户来说尤其重要
· 生成 代码质量 –以固定工作负载运行生成的可执行文件的秒数
o 对于技术计算、图形、游戏和其他性能密集型应用尤其重要
· 生成 代码大小 –二进制文件可执行部分的字节数
o 对于需要在较少内存上运行的应用程序尤其重要
在决定是否添加一个优化算法时,我们会考虑这三个方面对许多基准的影响。 在完美的世界中,Visual C++编译器可以花费无限的时间来编译并生成完美的二进制。 实际上,我们在合理的时间内进行折衷,以生成尽可能优化的二进制文件。 我们试图确保我们使用的优化算法具有适当的编译时间成本与代码质量和代码大小收益比。
我们运行什么场景/我们度量什么指标?
正确性测试的结果很容易报告-通过或失败,在失败的情况下提供足够的信息,说明什么东西没能深入问题。 性能测试更为棘手。 而不是黑或白的通过/失败,你有“我们相当肯定没有明显的变化”,“我们相当肯定有一个重大的变化”,或“有太多的变化来判断是否有变化”。 更糟糕的是,有些方面的表现正在改变,而另一些方面则没有;有的在进步,有的在倒退。 在一个极端情况下,您可以为性能的每一个微小部分报告数千个不同的指标。 这将淹没您的开发人员的数量,使他们永远需要解释他们。 在另一个极端,如果你报告的数字太少或错误的数字,你将隐藏重要的变化,因此错过回归。
一般来说,您希望报告尽可能少的指标,以使您能够最全面地覆盖您确定的场景。 鉴于这一[重大]警告,以下是我们决定监控的指标 并报告:
吞吐量
我们每天测量Windows和SQL的某些关键部分以及较小项目的编译时间,以便跟踪 吞吐量 . 在不太定期的基础上,我们计算了构建所有窗口所需的时间。 我们收集的指标是针对前端、后端和链接器的。 这总计为整个编译时间,但是它让我们可以更精确地分析性能回归的来源。
代码质量/代码大小
我们构建并运行了一套行业标准的整数和浮点基准测试,以监控优化代码生成的代码大小和代码质量。 每个基准测试都是真实世界的代码,但有CPU限制的特殊限制(不需要等待用户输入或大量读/写磁盘)。 我们运行的一些基准测试练习:加密算法、XML字符串处理、压缩、数学建模和人工智能。 我们还测量NT/SQL的代码大小变化。
为了 代码大小 我们使用“dumpbin.exe/headers
为了 代码质量 我们使用基准测试认为合适的任何度量来衡量生成代码的质量。 在许多情况下,这是执行时间,但在某些情况下,这可能类似于“抽象惩罚”或“每秒迭代次数”。 重要的是要注意度量中的一个较大的数字是好是坏,以便开发人员知道他们是在改进还是在回归它!
最小化可变性
跟踪性能的最大问题之一是,除了代码大小之外,结果 每一次的产量都不一样 . 与正确性测试用例不同 通过 或 失败 ,性能测试容易受到机器差异的影响,这些差异可以隐藏性能更改,或者在没有性能更改时显示性能更改。 为了提高结果的保真度,我们多次运行性能测试,并将结果合并为聚合值。 这样可以提高结果的准确性并消除异常值。
使用适当的聚合方法
我们发现绩效结果通常不具有正态分布;它们更接近于 歪斜 分配。 因此,使用中位数来聚合结果比使用 卑鄙的 在所有的结果中,它是更少的 易受 大的异常值。 您可以研究从性能运行中得到的结果的特征,并确定最佳聚合方法。 如果只有一个方向的异常值,那么使用最小值、最大值或四分位结果可能是最好的。 我们队主要使用中位数。
删除异常值
以下是一些删除异常值的简单方法:
· 删除结果的顶部和底部X%%
· 从样本平均值/中位数中去除X标准偏差以外的所有结果
除了丢弃一般的异常值之外,当二进制文件还没有加载到缓存中时,它的性能也会有很大的不同。 把第一次迭代作为热身跑可以抵消这一点。 注意:如果您的客户使用场景主要是在冷缓存上执行,那么您需要关注这个数字!
在运行基准测试之前先稳定机器
普通的windows机器上运行着很多服务,从sqlserver到IIS再到杀毒软件。 在执行基准测试之前关闭尽可能多的应用程序和服务将有助于减少可变性。 反病毒特别是重要的是禁用,因为所有的地方,它可以钩 并引入额外的开销。 禁用网络适配器也有助于降低噪音。
产生结果 可采取行动的
在这一点上,您有一组在稳定机器上运行多次迭代的基准测试,并且您正在将结果迭代集聚合为两个数字,即基线结果和更改的结果。 我们现在需要比较这些结果并确定它们是否:
1. 相同(无性能变化)
2. 不同(统计上显著的变化)
答。 显著改善
b。 显著回归
3. 不可操作(我们无法判断它们是相同的还是不同的)
如果结果足够准确,或者结果足够分离,那么就可以很容易地观察数字并判断数字属于哪一类。 但是,如果数字相当接近,或者您希望完全自动化此操作,您将需要一个更具体的算法来对结果进行分类。 这就是置信区间有用的地方——它们允许你说wi两组结果要么是相同的,要么是不同的,要么是你需要更多的迭代来判断一种方法或另一种方法。
进一步阅读
有关置信区间的更多信息,请参阅您最喜欢的统计书籍。 一本好书 涵盖了置信区间以及更多关于性能分析的内容 计算机系统性能分析的艺术 作者:Raj Jain。
谢谢你抽出时间 , ~z~皮特·施泰因 测试软件开发工程师 VC++代码生成团队–性能