2015-03-30 114 views
0

我的程序迭代给定的数据,我观察到一个奇怪的行为。算法处理的前几个样本表现出较慢的运行时间性能,但随后的样本和迭代运行几乎一致(运行时间比前几个样本/迭代运行时间相对较低)。算法的第一次迭代慢但后续的迭代运行良好

这是为什么?我甚至试图在迭代循环之外调用该函数作为热身函数调用,希望JVM能够优化代码,以便通过热身函数调用来实现。

// warm up function call 
warpInfo = warp.getDTW(testSet.get(startIndex), trainSet.get(0), distFn, windowSize); 

this.startTime = System.currentTimeMillis(); 
for(int i=startIndex; i<endIndex; i++) { 
    for(int j=0; j<trainSet.size(); j++) { 
     train = trainSet.get(j); 
     instStartTime = System.currentTimeMillis(); 
     warpInfo = warp.getDTW(test, train, distFn, windowSize); 
     if(warpInfo.getWarpDistance()<bestDist) { 
      bestDist = warpInfo.getWarpDistance(); 
      classPredicted = train.getTSClass(); 
     } 
     instEndTime = System.currentTimeMillis(); 
     instProcessingTime = instEndTime - instStartTime; 
     // record timiing and results here 
    } 
    // record other information here 
} 
+1

你可以请你分享你的代码与一些数据?没有这些信息,我们甚至无法搜索答案。 – JFPicard 2015-03-30 17:51:08

+1

JVM优化需要的不仅仅是一次调用来实际执行优化...... JVM将该循环看作热点并优化它 – 2015-03-30 17:51:37

+0

因此,您认为在这种情况下预热呼叫是无用的吗?它不会对代码优化产生任何影响? – 2015-03-30 18:03:25

回答

0

搜索后,我所遇到的几个环节SO Answer to a similar questionthis Java performance comparison具有运行程序告诉JVM这许多函数调用之后编译代码时指定-XX:CompileThreshold=1的选项。另请参阅Oracle Page。 用我的程序执行测试运行后,我可以说它解决了这个问题。

**编辑:**根据Zarev的评论,我会说我错了发布这个答案。 CompieThreshold标志只允许过早编译代码,因此它不会导致第一次迭代的运行时间更长,但实际上它可能会导致程序编译时不考虑细节。

+1

这根本不是问题。这只是JIT的工作方式。使用'-XX:CompileThreshold = 1',你会造成更多的伤害(实际上并不好)。 – 2015-03-30 18:47:31

+0

然后是否有一个JVM开关尽快编译字节码,除了提到的那个将是更好的选择。 – 2015-03-30 18:57:26

+0

快速编译代码毫无意义,因为这样可以防止JIT对其进行适当的配置和优化。您可以尝试使用'-XX:+ TieredCompilation',它可以在几个步骤中编译您的代码 – 2015-03-30 19:08:42