Java if 语句结构和指令流水线
Java if statement structure and instruction pipelining
问题:这更多的是出于好奇,而不是其他任何事情。如果我有一个 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/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 编译器...
你不能。 在字节码中没有标准化的表达方式。此外,优化器将代码转换为内部表示,这样的细节就会丢失。
过早的优化算了。编译器可以很好地完成更复杂的事情。一些低级优化仍然有意义,但仅限于非常极端的情况。寻求干净的代码,如果需要,也许一些高级优化。