问题:这更多是出于好奇。如果我有一个 Java if/else
语句,并且我知道“if/else”语句的一个分支将比另一个分支更频繁地被采用,那么我订购的方式是否可以两个分支向 JIT 编译器提供了一个提示,从而获得更好的性能?
背景: 在我对计算机体系结构的简单看法中,“if/else”语句被转换为条件跳转指令,后跟如果未执行跳转则应执行的指令。内存中的其他地方将是跳转所针对的代码。据我了解,CPU 会尽可能地按顺序加载指令(我确定我在这里忽略了分支预测器),并且非跳转路径更有可能被加载到指令缓存和 CPU 的指令流水线。
问题重述:if/else
语句的分支的合理排序能否增加经常执行的代码紧跟条件跳转指令的可能性,从而呈现代码对缓存和管道更友好?
现实:听到 JIT 编译器是一个如此复杂的软件,在完成所有指令重新排序、寄存器分配和其他簿记之后,我不会感到惊讶,它可以'不要做出这样的保证。
我的大部分“if/else”语句都不会执行,所以我不会在任何地方都这样做。此外,很多时候我会猜错哪个分支将更频繁地执行,最终实际上会损害性能。
我想认为像故意使用分支排序这样简单的事情不会被认为是过早的优化,但如果是这样,我只会在探查器向我显示代码很慢时才弄乱排序。
谢谢!
最佳答案
没有。
你不能。你不需要。
这对编译器来说有一定的意义,因为它可以翻译
if (improbable) {
doSomething();
} else {
doSomethingElse();
}
doMoreThings();
return;
进入(伪代码)
if (improbable) goto away
doSomething()
back: doMoreThings()
return
away: doSomethingElse()
goto back
这样更可能的路径就被精简了。一个AOT编译器可以依赖所提供的信息。
您不需要。但是 Java 会做这些事情 JIT编译器在收集统计信息后始终如此。在这里,javac
是无关紧要的,因为字节码被解释器执行了几次,这很慢,但对于很少执行的部分来说已经足够好了,也足以收集统计数据。通常,这些统计数据比程序员可能提供的要好,但更重要的是:它们是为每个与时间相关的代码片段收集的。它实际上更复杂,因为那里有 C1 和 C2 编译器......
你不能。在字节码中没有标准化的表达方式。此外,优化器将代码转换为内部表示,这样的细节就会丢失。
过早的优化 算了吧。编译器可以很好地完成更复杂的事情。一些低级优化仍然有意义,但仅限于非常极端的情况。寻求干净的代码,如果需要,也许一些高级优化。
关于Java if 语句结构和指令流水线,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38491758/