使用Java创建快速/可靠的基准测试?

| 我正在尝试使用Java创建基准测试。目前,我有以下简单方法:
public static long runTest(int times){
    long start = System.nanoTime();     
    String str = \"str\";
    for(int i=0; i<times; i++){
        str = \"str\"+i;
    }       
    return System.nanoTime()-start;     
}
我当前在另一个循环中多次发生此循环,该循环发生了多次,并获得了运行此方法所需的最小/最大/平均时间。然后,我在另一个线程上开始一些活动,然后再次进行测试。基本上,我只是想获得一致的结果...如果我有1000万次runTest循环,这似乎很一致:
Number of times ran: 5
The max time was: 1231419504 (102.85% of the average)
The min time was: 1177508466 (98.35% of the average)
The average time was: 1197291937
The difference between the max and min is: 4.58%

Activated thread activity.

Number of times ran: 5
The max time was: 3872724739 (100.82% of the average)
The min time was: 3804827995 (99.05% of the average)
The average time was: 3841216849
The difference between the max and min is: 1.78%

Running with thread activity took 320.83% as much time as running without.
但这似乎有点多,并且要花一些时间...如果我在runTest循环中尝试使用较小的数字(100000),则会变得非常不一致:
    Number of times ran: 5
    The max time was: 34726168 (143.01% of the average)
    The min time was: 20889055 (86.02% of the average)
    The average time was: 24283026
    The difference between the max and min is: 66.24%

    Activated thread activity.

    Number of times ran: 5
    The max time was: 143950627 (148.83% of the average)
    The min time was: 64780554 (66.98% of the average)
    The average time was: 96719589
    The difference between the max and min is: 122.21%

    Running with thread activity took 398.3% as much time as running without.
有没有办法我可以做一个这样的基准,它既一致又高效/快速? 顺便说一下,我没有测试开始时间和结束时间之间的代码。我正在以某种方式测试CPU负载(请参阅我如何开始一些线程活动并重新测试)。因此,我认为我正在寻找的东西可以替代“ runTest”中的代码,从而产生更快,更一致的结果。 谢谢     
已邀请:
        简而言之: (微型)基准测试非常复杂,因此请使用基准测试框架http://www.ellipticgroup.com/misc/projectLibrary.zip之类的工具-并对结果仍然持怀疑态度(\“将微型信任放入微型-benchmark \“,Dr。Cliff Click)。 详细地: 有很多因素会严重影响结果: System.nanoTime的准确性和精确度:在最坏的情况下,它与System.currentTimeMillis一样糟糕。 代码预热和类加载 混合模式:仅在足够频繁地调用代码块(1500或1000次)之后,JVM的JIT编译(请参见Edwin Buck的回答) 动态优化:取消优化,堆栈替换,消除无效代码(您应该使用循环中计算出的结果,例如打印出来) 资源回收:垃圾收集(请参阅Michael Borgwardt的答案)和对象完成 缓存:I / O和CPU 您的操作系统总体上:屏幕保护程序,电源管理,其他进程(索引器,病毒扫描等) Brent Boyer的文章“严格的Java基准测试,第1部分:问题”(http://www.ibm.com/developerworks/java/library/j-benchmark1/index.html)很好地描述了所有这些内容。问题以及您是否/可以采取哪些措施(例如,使用JVM选项或事先调用ProcessIdleTask)。 您将无法消除所有这些因素,因此进行统计是个好主意。但: 而不是计算最大值和最小值之间的差,您应该努力计算标准偏差(结果{1,1000×2,3}与{501×1,501×3}不同)。 通过产生置信区间(例如,通过自举)来考虑可靠性。 上面提到的Benchmark框架(http://www.ellipticgroup.com/misc/projectLibrary.zip)使用了这些技术。您可以在Brent Boyer的文章“严格的Java基准测试,第2部分:统计和解决方案”(https://www.ibm.com/developerworks/java/library/j-benchmark2/)中阅读有关它们的信息。     
        您的代码最终主要测试垃圾回收性能,因为在循环中附加到String最终会创建并立即丢弃大量越来越大的String对象。 这是固有地导致测量值发生巨大变化的原因,并且受到多线程活动的强烈影响。 我建议您在循环中执行其他一些具有更可预测的性能的操作,例如数学计算。     
        在运行一千万次之后,HotSpot编译器很有可能检测到“大量使用”的代码并将其编译为机器本机代码。 解释了JVM字节码,这导致它容易受到来自JVM中发生的其他后台进程(如垃圾回收)的更多中断的影响。 一般来说,这类基准测试充满了不成立的假设。您无法相信一个微型基准测试确实可以证明它打算证明的事实,而没有大量证据证明初始测量(时间)实际上并没有测量您的任务以及可能还有其他一些背景任务。如果您不尝试控制后台任务,则该测量的用途将大大减​​少。     

要回复问题请先登录注册