(如何)Java JIT编译器优化我的代码?

时间:2011-11-24 11:19:20

标签: java jit compiler-optimization

我正在编写相当低级别的代码,必须对速度进行高度优化。每个CPU周期都很重要。由于代码是用Java编写的,所以我不能像C中那样写低级别,但是我想从虚拟机中获取所有内容。

我正在处理一个字节数组。我的代码有两个部分,我现在主要感兴趣。第一个是:

int key =  (data[i]     & 0xff)
        | ((data[i + 1] & 0xff) <<  8)
        | ((data[i + 2] & 0xff) << 16)
        | ((data[i + 3] & 0xff) << 24);

,第二个是:

key = (key << 15) | (key >>> 17);

从性能来看,我猜这些陈述没有像我期望的那样优化。第二个陈述基本上是ROTL 15, key。第一个语句将4个字节加载到int中。如果访问的字节恰好为负,则0xff掩码仅用于补偿由隐式转换为int导致的添加符号位。这应该很容易转换为高效的机器代码,但令我惊讶的是,如果我删除了掩码,性能会上升。 (这当然会破坏我的代码,但我很想知道会发生什么。)

这里发生了什么?最常见的Java VM是否会在JIT期间以期望优秀的C ++编译器优化等效C ++代码的方式优化此代码?我可以影响这个过程吗?设置-XX:+AggressiveOpts似乎没有任何区别。

(CPU:x64,平台:Linux / HotSpot)

4 个答案:

答案 0 :(得分:7)

答案 1 :(得分:5)

我已经在Java中完成了很多性能代码,我甚至直接在Bytecode中编码,足以确定一些事情:JIT是一个带有模糊行为的黑盒子,JIT和编译器都令人难以置信高效,最简单的代码通常可以产生最佳性能。

当您考虑JIT的目标时,这是正常的:从任何Java代码中提取最佳性能。当你添加Java是一个非常简单和简单的语言时,简单的代码将被优化,任何进一步的技巧通常都不会有好处。

当然,您应该知道一些常见的陷阱和陷阱,但我在您的代码示例中没有看到任何陷阱。如果我要优化您的代码,我会直接进入更高级别:算法。代码的复杂性是多少?可以缓存一些数据吗?使用了什么API?等等......单独从算法技巧中提取出一个看似无穷无尽的性能坑。

即使这还不够,如果语言不够快,如果你的机器不够快,如果你的算法不能更快,那么答案就不在于“时钟周期”,因为你可能会挤出20%的效率,但是当数据增长时,20%将永远不够。为了确保你永远不会再打一个性能墙,最终的答案在于可扩展性:让你的算法和你的数据无休止地分配,这样你就可以让更多的工作人员完成任务。

答案 2 :(得分:3)

我同意solendil,但如果你想深入挖掘低级别,请尝试按照here所述获取JIT生成的代码。

答案 3 :(得分:0)

在将24位向左移位之前,您不需要(&amp; 0xff)。