[英]Why there is no infrastrucutre for hinting JIT compiler in JVM?
我正在審查一個觸及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);
}
}
作為一名程序員,我可能知道有一個編譯器不知道的優化領域。 例如,如果multiplyByTwo
將被強制內聯,則可以進行大量優化,但是由於各種約束(例如方法大小或內聯深度),它可以從內聯中省略。 為什么沒有辦法告訴編譯器“嘿,我很確定你應該更喜歡內聯那個方法而不是”? 我敢肯定,我不是第一個考慮這個問題的人,並且討論導致沒有實現這樣的功能 - 為什么?
ps請注意我正在談論提示而不是指令; 我明白后一種選擇會帶來更多的傷害而不是利益。
實際上, 有一個控制HotSpot JVM編譯器的基礎設施。
您可以使用-XX:CompileCommandFile=
JVM選項指定包含編譯器命令的文件。 有一些命令強制內聯,從編譯中排除方法,設置每個方法選項(例如MaxNodeLimit
)等等。 可以在此處找到可用命令的完整列表。
編譯器命令文件的示例可能如下所示
inline java.util.ArrayList::add
exclude *::<clinit>
print com.example.MyClass::*
JDK特定的注釋是控制JVM優化的另一種方法。 HotSpot JVM知道某些注釋,例如
@java.lang.invoke.ForceInline
@java.lang.invoke.DontInline
@java.lang.invoke.Stable
@sun.misc.Contended
注意:所有這些機制都是非標准的。 它們僅適用於OpenJDK和Oracle JDK。 沒有標准的方法來提示JVM編譯器,因為有許多JVM實現具有完全不同的編譯策略。 特別是,有些JVM根本沒有JIT編譯。
好吧,這是 JVM優化器的提示,這個方法是內聯的一個很好的候選者:
static
或private
,即不可覆蓋的 實際上,您假設此方法是一個很好的候選者是基於相同的技術證據,因此添加一個暗示, 您認為這是一個好的內聯候選者不會添加任何新信息,只會添加冗余。
因此,如果JVM仍然沒有內聯該方法,無論出於何種原因,盡管所有這些技術屬性都在內聯,但沒有理由假設非強制性,非技術性提示,很可能源於相同的技術屬性將改變JVM的決定。
你可以選擇你想要的任何潛在理由,防止某些問題,限制性太強,甚至是有缺陷的JVM實現,在任何一種情況下,你都會看到同樣的原因也適用於具有你提示的方法,即使它已經轉向這是一個沒有根據的理由,因為這也適用於沒有提示的方法。 因此在后一種情況下,顯而易見的解決方案是修復JVM中的缺陷,而不是添加一般提示機制。
一般的提示機制尤其值得懷疑,因為代碼應該是平台無關的。 如果您在具有特定JVM實現的已知環境中查看特定運行,則情況會有所不同。 例如,HotSpot支持-XX:CompileCommand
選項。 所以在你的情況下,你可以使用-XX:CompileCommand=inline,your/class/Name,multiplyByTwo
來試圖說服JVM內聯方法。 當然,正確的拼寫很重要。 在你的問題中,該方法曾被命名為multipleByTwo
,然后multiplyByTwo
...
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.