Java 为什么JVM中没有提示JIT编译器的基础结构?
我在回顾一个涉及JIT内联语义的会议演示,其中作者指出了奇怪的行为(当然,只有第一眼看到时才奇怪)——C2比C1慢,因为它无法内联方法,因为内联深度过大。它可以在以下示例中表示:Java 为什么JVM中没有提示JIT编译器的基础结构?,java,jvm,jit,Java,Jvm,Jit,我在回顾一个涉及JIT内联语义的会议演示,其中作者指出了奇怪的行为(当然,只有第一眼看到时才奇怪)——C2比C1慢,因为它无法内联方法,因为内联深度过大。它可以在以下示例中表示: public static int multipleByTwo(int x) { return x * 2; } public static void entrypoint() { int sum = 0; for (int i = 0; i < 10_000_000; i++) {
public static int multipleByTwo(int x) {
return x * 2;
}
public static void entrypoint() {
int sum = 0;
for (int i = 0; i < 10_000_000; i++) {
// due to some arbitrary cause, multiplyByTwo doesn't get inlined
sum += multiplyByTwo(i);
}
}
公共静态整数倍增two(整数x){
返回x*2;
}
公共静态void入口点(){
整数和=0;
对于(int i=0;i<10_000;i++){
//由于某些任意原因,multiplyByTwo无法内联
总和+=乘以2(i);
}
}
作为一名程序员,我可能知道有一个编译器不知道的优化领域。例如,如果multiplyByTwo
将被强制内联,则可能存在大量优化,但由于各种限制(例如方法大小或内联深度),可能会从内联中忽略。为什么没有办法告诉编译器“嘿,我很确定你应该更喜欢内联该方法而不是它”?我肯定我不是第一个想到这一点的人,有人讨论过没有实现这样的功能——为什么
p、 请注意,我说的是提示而不是指令;我知道后一种选择弊大于利。好吧,JVM的优化器得到的提示是,这种方法是内联的一个很好的候选方法:
- 它是
或静态的
,即不可重写私有的
- 非常短
- 它在一个循环中被调用了好几次
-XX:CompileCommand
选项。所以在你的情况下,你可以使用
-XX:CompileCommand=inline,您的/class/Name,multiplyByTwo
试图说服JVM内联该方法。当然,正确的拼写很重要。在您的问题中,该方法曾经被命名为multipleByTwo
,然后multipleByTwo
…事实上,有一个基础结构来控制HotSpot JVM编译器
1.编译器命令文件
您可以使用-XX:compileCommand=
JVM选项指定包含编译器命令的文件。有强制内联、从编译中排除方法、设置每个方法选项(例如,MaxNodeLimit
)等命令。可以找到可用命令的完整列表
示例编译器命令文件可能如下所示
inline java.util.ArrayList::add
exclude *::<clinit>
print com.example.MyClass::*
内联java.util.ArrayList::add
排除*::
打印com.example.MyClass::*
2.注释
JDK特定注释是控制JVM优化的另一种方法。HotSpot JVM知道某些注释,例如
注意:所有这些机制都是非标准的。它们仅适用于OpenJDK和Oracle JDK。没有标准的方法来提示JVM编译器,因为有许多JVM实现具有完全不同的编译策略。特别是,有些JVM根本没有JIT编译。确定何时以及如何通过JIT优化运行时的AI算法(如方法内联)非常难掌握。但使方法“final”可以提示java将其内联。好吧,没有任何方法可以告诉JIT确定方法是内联的。如果最大内联深度更大,这个问题可能会消失——问题就是这样;或者,为什么不能使用JVM参数来增加深度呢。更一般地说,问题是“为什么JIT在Y时停止进行X优化”:因为JIT的作者不能花费无限的时间来确保每个可能的情况都得到处理。它在大多数情况下都能很好地工作。@vvtx是的,我知道我不能口述编译器(至少在现代jvm中是这样)。我的问题是“为什么没有人实现它?”而不是“如何强制编译器按照我的意愿内联?”@AndyTurner是的,我知道最大内联深度。但开发人员可能会提示编译器,如果他确信这样做将有利于整体性能,那么它应该更深入地内联一个方法,而不是从顶部内联(保持指定的深度)。整个问题不是关于内联本身,它只是展示了一个示例,其中开发人员入侵可能会带来性能好处,但是,由于未知原因,入侵是不可能的——我想知道这个原因。我的评论不是关于内联本身。它指出,JIT尝试优化的价值必然存在实际的局限性,而且它在绝大多数情况下都能很好地工作,这一事实消除了暗示机制的额外复杂性。我知道内联规则(顺便说一句,我听过很多次)