Java JIT循环展开策略?

10

JIT的循环展开策略是什么?如果没有简单的答案,那么我可以通过某种方式检查循环中何时/在哪里执行了循环展开吗?

GNode child = null;
for(int i=0;i<8;i++){
   child = octree.getNeighbor(nn, i, MethodFlag.NONE);
   if(child==null)
      break;
   RecurseForce(leaf, child, dsq, epssq);
}

我有一段代码,循环次数是固定的(八次),如果我不对for循环进行任何修改,它的效果很差。但是当我手动展开这个循环时,它的效果显著提高了。我想知道JIT是否实际上展开了循环,如果没有,那么为什么。


7
这是一个非常具体的问题,你需要针对特定版本的特定JVM和特定平台进行分析。而且我想,“为什么”只能通过深入分析JIT代码才能回答。 - Joachim Sauer
你遗漏了一个至关重要的细节:你使用的是哪个JVM? - aioobe
@aioobe 这是Java Hotspot 64位,1.6.x版本。 - R.K
2个回答

6

如果JVM展开循环,最好的答案可能是通过实际打印生成的汇编代码来回答。请注意,这需要您的代码实际上被执行为热点(即JVM认为它值得昂贵的优化)。

为什么JVM决定采取一种方式还是另一种方式是一个更难回答的问题,可能需要深入分析JIT代码。


谢谢。打印汇编代码可能是一种可行的方法,但我想知道是否有任何公开的API可以查看此内容。例如,当JIT执行循环展开时调用的方法,我可以计算它被调用的次数以及调用它的上下文。我已经查看了JVMTI,但没有找到任何相关信息。 - R.K
我非常确定没有这样的API,因为这是高度依赖于实现的,并且对于大多数应用程序来说只有有限的用途。 - Joachim Sauer
谢谢。我想我在玩JVMTI和Eclipse JDT后期望太高了。 - R.K
2
实际上整个事情不仅仅是实现和代码特定的,甚至可以通过命令行选项来影响它。看一下-XX:LoopUnrollLimit= - Voo

1

另一种查看循环展开是否在循环中执行的方法是在运行代码时将-XX:LoopUnrollLimit=1指定为JVM的参数

如果您有一个可执行的jar文件,那么可以这样使用:

java -XX:LoopUnrollLimit=1 -jar your-jar.jar

这个标志将会:

展开循环体,但只针对服务器编译器中间表示节点计数小于此值的循环

这将直接回答您的问题,无需查看生成的汇编代码。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接