我回顾了一个讨论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++) {
// due to some arbitrary cause, multiplyByTwo doesn't get inlined
sum += multiplyByTwo(i);
}
}
作为一个程序员,我可能知道有一个编译器不知道的优化领域。e、 g.如果可能的话,有很多优化 multiplyByTwo
将强制内联,但由于各种限制(例如方法大小或内联深度),可能会从内联中忽略它。为什么没有办法告诉编译器“嘿,我很确定你应该更喜欢内联那个方法而不是”?我肯定我不是第一个想到这一点的人,有人讨论过没有实现这样的功能-为什么?
p、 请注意,我说的是提示而不是指令;我明白后一种选择会带来弊大于利。
2条答案
按热度按时间but5z9lq1#
事实上,有一个基础设施来控制热点jvm编译器。
1. 编译器命令文件
您可以指定一个包含编译器命令的文件
-XX:CompileCommandFile=
jvm选项。有命令可以强制内联、从编译中排除方法、设置每个方法选项(例如。MaxNodeLimit
)等等。可以在这里找到可用命令的完整列表。编译器命令文件的示例如下
2. 注解
特定于jdk的注解是控制jvm优化的另一种方法。hotspot jvm知道某些注解,例如。
@java.lang.invoke.ForceInline
@java.lang.invoke.DontInline
@java.lang.invoke.Stable@sun.misc.Contended
注:所有这些机构都是非标准的。它们只适用于openjdk和oraclejdk。没有标准的方法来提示jvm编译器,因为有许多jvm实现具有完全不同的编译策略。特别是,有些jvm根本没有jit编译。qlvxas9a2#
好吧,以下是对jvm优化器的提示,说明此方法是内联的一个很好的候选方法:
是的
static
或者private
,即不可重写它非常短
它在一个循环中被多次调用
事实上,您认为此方法是一个好的候选方法的假设是基于相同的技术证据,因此添加一个您认为这是一个好的内联候选方法的提示不会添加任何新信息,只会增加冗余。
因此,如果jvm仍然没有内联该方法,不管出于什么原因,尽管所有这些技术属性都表示内联,但没有理由认为一个非强制性的、非技术性的提示(很可能来自相同的技术属性)会改变jvm的决定。
您可以选择任何您想要的潜在原因,针对某些问题的保护,过于严格的限制,甚至是有缺陷的jvm实现,在这两种情况下,您将看到同样的原因也适用于有您的提示的方法,即使它被证明是一个没有根据的原因,因为这也适用于没有您的提示的方法。因此,在后一种情况下,显而易见的解决方案是修复jvm中的缺陷,而不是添加通用的提示机制。
一般的暗示机制尤其值得怀疑,因为代码应该是独立于平台的。如果您在已知环境中使用特定的jvm实现查看特定的运行,情况会有所不同。e、 g.热点支持
-XX:CompileCommand
选项。所以在你的情况下,你可以-XX:CompileCommand=inline,your/class/Name,multiplyByTwo
试图说服jvm内联该方法。当然,正确的拼写很重要。在您的问题中,方法曾经被命名为multipleByTwo
,那么multiplyByTwo
…