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

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

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

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

第二个是:

 key = (key <>> 17); 

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

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

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

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

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

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

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

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

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