一部のJVMは、Javaバイトコードをネイティブマシンコードにコンパイルします。そのために適用できる最適化はたくさんあります。最近、CPUが誤った予測を行うと、分岐操作がCPUをブロックし、パフォーマンスに大きな影響を与える可能性があることも学びました。
収集された実行時統計に基づいて、JVMがCPUがマシンコードをより簡単に生成して正しい予測を行うかどうか誰かが知っていますか?
一部のJVMは、Javaバイトコードをネイティブマシンコードにコンパイルします。そのために適用できる最適化はたくさんあります。最近、CPUが誤った予測を行うと、分岐操作がCPUをブロックし、パフォーマンスに大きな影響を与える可能性があることも学びました。
収集された実行時統計に基づいて、JVMがCPUがマシンコードをより簡単に生成して正しい予測を行うかどうか誰かが知っていますか?
回答:
いいえ、HotSpotはOpenJDKメーリングリストに記載されているように、ハードウェアブランチプレディクターにヒントを追加しません。
それは検討され、反対されました。openjdkが現在対象としているプラットフォームはすべて、見事なハードウェアブランチ予測に適しています。ナイアガラ1など、そうしなかったものは予測ビットを無視しました。結論は、Davidが言うように、「マジックマクロ」でコードを複雑にする価値はないということです。
私の推測では、機械命令レベルでの予測ヒントはせいぜいノイズであり、最悪の場合、最新のアウトオブオーダーの投機的実行アーキテクチャーでの損害(無駄な命令バイト)です。そうすることは、CPUに動作を弱めるように指示するようなものです。つまり、CPUが実行するように設計されている、すでにインテリジェントなことをやめるように指示します。
第2に、分岐予測をどの程度改善できるかは、予測ミスの原因と、分岐のパフォーマンス効果を測定したり分岐の傾向を観察したりする容易さによって異なります。
ただし、CPU分岐の予測ミスカウンターの助けがなくても、既存のJIT最適化トリックのバッグはすでに分岐予測をある程度改善できると思います。
非常に単純なコード例:
public void repeatHistory(int value)
{
if (value == 1492)
{
landing();
}
else if (value == 1776)
{
ratifying();
}
}
それrepeatHistory
が何度も呼び出されると仮定します。ときに、サンプリングベースのパフォーマンスモニタは、コールスタックの統計を分析し、それが、何らかの理由でそれを見つけるかもしれrepeatHistory()
呼び出しは、ratifying()
かつての呼び出しよりも頻繁に発生しますlanding()
。この観察に基づいて、repeatHistory
メソッドのJITコード生成の次のパスはこれを考慮に入れ、1つ以上の最適化を実行します。
(value == 1776)
前にチェックを移動します(value == 1492)
ratifying()
メソッドをブランチにインライン化しようとするrepeatHistory()
repeatHistory()
別のループから呼び出された場合は、ループを展開するか、repeatHistory()
メソッドをそのループにインライン化してください。最適化を1つ適用した後、最適化を適用できるかどうかを再度分析して、最適化を適用できるかどうかを確認する必要があることがよくあります。