鉴于在部署时我不知道我的代码将在哪种系统上运行,我如何编写一个性能基准测试,以系统的潜力作为衡量标准。
我的意思是,如果一个系统能够每秒运行一段代码 1000 次,我希望测试以确保它尽可能接近 1000。如果它只能做到 500,那么这就是我想与之比较的比率。
如果它有助于使答案更具体,我正在使用 JUnit4。
谢谢你。
鉴于在部署时我不知道我的代码将在哪种系统上运行,我如何编写一个性能基准测试,以系统的潜力作为衡量标准。
我的意思是,如果一个系统能够每秒运行一段代码 1000 次,我希望测试以确保它尽可能接近 1000。如果它只能做到 500,那么这就是我想与之比较的比率。
如果它有助于使答案更具体,我正在使用 JUnit4。
谢谢你。
出于几个原因,我不会将单元测试用于性能测试。
首先,单元测试不应该依赖于周围的系统/代码。性能测试在很大程度上取决于硬件/操作系统,因此很难获得可在开发人员工作站、构建服务器等上使用的统一度量。
其次,单元测试应该执行得非常快。当您进行性能测试时,您通常希望拥有相当大的数据集并重复运行数次以获得平均数/消除开销等。这些都与快速测试的想法背道而驰。
测试意味着您有一个通过/失败阈值。对于性能测试,这意味着太慢而您失败,足够快则您通过。如果你失败了,你就开始返工。
如果你不能失败,那么你是在进行基准测试,而不是实际测试。
当您谈论“系统能够运行”时,您必须定义“能够”。您可以使用大量硬件性能基准测试中的任何一个。油石、Dhrystone 等很受欢迎。或者,也许您有一个数据库密集型应用程序,那么您可能想查看 TPC 基准。或者,也许您有一个网络密集型应用程序并想使用 netperf。或者是 GUI 密集型应用程序并希望使用某种图形基准。
这些中的任何一个都可以为您提供某种“能力”测量。选择一个或多个。他们都很好。同样值得商榷。同样偏向您的竞争对手和远离您。
运行基准测试后,您就可以运行您的软件并查看系统实际执行的操作。
你可以——如果你收集到足够的数据——在一些基准数据和你的性能数据之间建立一些相关性。您将看到基于工作负载、硬件配置、操作系统版本、虚拟机、数据库服务器等的各种变化。
从足够多的盒子和足够多的不同配置中获得足够的数据,您最终将能够开发出一个性能模型,该模型表示“鉴于此硬件、软件、调整参数和配置,我希望我的软件每秒执行 [X] 个事务”。这是“有能力”的明确定义。
拥有该模型后,您可以将您的软件与功能编号进行比较。在你拥有一个非常完整的模型之前,你并不真正知道哪些系统甚至能够每秒运行这段代码 1000 次。
我同意Brian的观点,他说单元测试不是进行性能测试的合适方法。但是,我整理了一个简短的示例,可以用作集成测试以在不同的系统配置/环境上运行。
请注意,这只是为了说明在这方面可以做什么,并没有提供足够精确的结果来支持任何关于系统性能的官方声明。
import static org.junit.Assert.*;
import org.junit.Test;
package com.stackoverflow.samples.tests {
@Test
public void doStuffRuns500TimesPerSecond() {
long maximumRunningTime = 1000;
long currentRunningTime = 0;
int iterations = 0;
do {
long startTime = System.getTimeMillis();
// do stuff
currentRunningTime += System.getTimeMillis() - startTime;
iterations++;
}
while (currentRunningTime <= maximumRunningTime);
assertEquals(500, iterations);
}
}
我对用于实时系统的代码的测试进行了一些时间测量,其中计算时间过长的正确答案是失败的。
我所做的只是绘制测试接管最近构建的增量 cpu 时间。请注意,CPU 时间不是实时的。实际值并不重要——重要的是它改变了多少。
如果我对显着改变测试运行时间的算法进行更改,我可以轻松放大到导致它的特定变更集。我真正关心的是这些兴趣点——不一定是绝对值。在实时系统中经常有很多权衡,这些不能总是以简单的比较来表示给测试框架。
首先查看绝对时间并将它们标准化似乎是合理的,但实际上您的系统和目标系统之间的转换将是非线性的 - 例如缓存压力、交换使用、目标系统上的磁盘速度等可能会导致时间测试以与您的系统不同的阈值爆炸。
如果您绝对需要在这方面准确的测试,请复制目标系统并将其用作测试从属系统,但在您期望的类似环境中。
在我的情况下,它实际上可能正在将固件下载到 DSP,远程重启它,从串行端口读取响应或因为它崩溃而看不到响应!
--杰夫克++