作为性能测试套件的一部分,我们有一个简单的单元测试,用于在甚至开始测试代码之前验证基本系统是否正常运行。这样,我们通常会验证机器是否适合运行实际性能测试。
当我们使用此测试比较Java 6和Java 7时,Java 7需要花费更长的时间来执行!我们看到Java 6平均为22秒,Java 7为24秒。该测试仅计算斐波那契,因此此处仅涉及单个线程中的字节码执行才有意义,而与I / O无关。
当前,我们在带有或不带有“-server”的Windows上以默认设置运行它,同时具有32位和64位JVM,所有运行都表明Java 7有类似的降级。
哪些调整选项可能适合尝试将Java 7与Java 6进行匹配?
public class BaseLinePerformance {
@Before
public void setup() throws Exception{
fib(46);
}
@Test
public void testBaseLine() throws Exception {
long start = System.currentTimeMillis();
fib(46);
fib(46);
System.out.println("Time: " + (System.currentTimeMillis() - start));
}
public static void fib(final int n) throws Exception {
for (int i = 0; i < n; i++) {
System.out.println("fib(" + i + ") = " + fib2(i));
}
}
public static int fib2(final int n) {
if (n == 0)
return 0;
else if (n == 1)
return 1;
else
return fib2(n - 2) + fib2(n - 1);
}
}
更新:我已将测试减少为不做任何睡眠,并遵循How do I write a correct micro-benchmark in Java?的其他建议,但我仍然看到Java 7和Java 6之间存在相同的区别,用于打印编译和GC的其他JVM选项在测试期间不显示任何输出。实际测试中,仅打印最初的编译信息。
最佳答案
我的一位同事经过进一步的挖掘发现了原因:
有一个JVM标志-XX:MaxRecursiveInlineLevel,其默认值为1。在以前的版本中,此设置的处理似乎不正确,因此Sun / Oracle在Java 7中“修复”了该问题,但是有副作用。有时内联现在执行起来不太积极,因此递归代码的纯运行时/ CPU时间可能比以前更长。
我们正在测试将其设置为2,至少对于所涉及的测试,其行为与Java 6相同。