Javaの脱出問題の心得
newのオブジェクトは全部ヒープに割り当てられていると思われますが、これは完全に正確ではありません。Javaオブジェクトの割り当て過程を分析してみると、対象はヒープに割り当てられる以外に、スタックやTLABに空間を割り当てることができます。スタック上で対象を割り当てる技術的基礎は脱出分析とスカラー置換であり、本稿では主に脱出分析を紹介する。
脱出分析の定義
エスケープ解析は、Javaプログラムにおける同期負荷とメモリスタック割り当て圧力を効果的に減らすことができる関数的大域データストリーム解析アルゴリズムである。
逸脱解析により、Java Hotspotコンパイラは、新しいオブジェクトの参照の使用範囲を分析して、このオブジェクトをヒープに割り当てるかどうかを決定することができます。
Javaは、Java SE 6 u 23および以降のバージョンでサポートされ、デフォルトでエスケープ分析のオプションを開きました。JavaのHotSpot JITコンパイラは、方法でコードをリロードしたり、動的にコードをロードしたりする時にコードを逸脱分析することができます。
脱出分析の基本的な挙動は,解析対象の動的作用領域である。対象が方法で定義された場合には,外部法によって引用される可能性がある。
方法脱出:例えば、呼び出しパラメータとして他の方法に渡す。
スレッド逸脱:外部スレッドにアクセスされる可能性があります。例えば、クラス変数に値を割り当てたり、他のスレッドにアクセスできる変数の例があります。
脱出分析の理論基礎
Jong-Deok Choi、Manish Gropta、Mauricio Seffano、Vugram C.Sreedhar、Sam Midkiffなどに基づいて、論文「Escape Analysis for Java」で説明したアルゴリズムは、逸脱分析を行います。
このアルゴリズムは,連結図を導入して,オブジェクトとオブジェクト参照との間の到達可能性関係を構築し,サブベースで,結合データ・ストリーム解析法を提案する。このアルゴリズムはコンテキスト依存性と流れに敏感であり,オブジェクトの任意の階層の入れ子関係をシミュレーションしているので,解析精度が高く,実行時間とメモリ消費が比較的大きいだけである。
ほとんどのエスケープ分析の実現は「クローズドワールド」の前提に基づいています。実行可能なすべての方法はエスケープ分析をする前にすでに知っています。そして、プログラムの実行はそれらの間の呼び出し関係を変えられません。しかし、実際のJavaプログラムが実行されると、このような仮定は成立しません。Javaプログラムが持つ多くの特性、例えば、ダイナミッククラスのローディング、ローカル関数の呼び出し、反射プログラムの呼び出しなど、いわゆる「閉じた世界」という約束を破る。
脱出分析後の処理操作
脱出分析を経て、対象の3つの可能な逃亡状態を得ることができる。
GlobalEscape(グローバル逸脱):つまり、オブジェクトの引用は、方法またはスレッドから逸脱しています。例えば、オブジェクトの参照は、クラス変数にコピーされたものであり、またはすでに逸脱しているオブジェクトに格納されているもの、または、このオブジェクトの参照は、方法の戻り値として呼び出された方法に返される。
ArgEscape(パラメータレベル逸脱):方法呼び出し中にオブジェクトを転送するアプリケーションを一つの方法に適用します。この状態は調整された方法のバイナリコードを解析して決定できる。
NoEscape(エスケープなし):スカラー置換が可能なオブジェクト。このオブジェクトは伝統的なヒープに割り当てられないことができます。
コンパイラは逸脱分析の結果を使ってプログラムを最適化できます。
スタック割り当ての対象はスタック割り当ての対象となります。一つの方法の中のオブジェクトは、オブジェクトの参照が逸脱していない場合、この方法はスタックメモリ上の非常に見られるスタックメモリ上に割り当てられるかもしれません。
同期をなくす:スレッド同期の代償はかなり高く、同期の結果は同時性と性能を低下させる。逸脱解析は、あるオブジェクトが常に一つのスレッドにしかアクセスされていないかどうかを判断し、一つのスレッドにのみアクセスされると、そのオブジェクトに対する同期動作は、同期保護されていない動作に転化することができ、これによって、合併の度合いと性能を大幅に向上させることができる。
ベクトル代替:逃散分析方法対象のメモリ格納構造が連続して行う必要がないと発見された場合、対象の一部または全部をCPUレジスタに保存することができ、アクセス速度を大幅に向上させることができる。
脱出分析の定義
エスケープ解析は、Javaプログラムにおける同期負荷とメモリスタック割り当て圧力を効果的に減らすことができる関数的大域データストリーム解析アルゴリズムである。
逸脱解析により、Java Hotspotコンパイラは、新しいオブジェクトの参照の使用範囲を分析して、このオブジェクトをヒープに割り当てるかどうかを決定することができます。
Javaは、Java SE 6 u 23および以降のバージョンでサポートされ、デフォルトでエスケープ分析のオプションを開きました。JavaのHotSpot JITコンパイラは、方法でコードをリロードしたり、動的にコードをロードしたりする時にコードを逸脱分析することができます。
脱出分析の基本的な挙動は,解析対象の動的作用領域である。対象が方法で定義された場合には,外部法によって引用される可能性がある。
方法脱出:例えば、呼び出しパラメータとして他の方法に渡す。
スレッド逸脱:外部スレッドにアクセスされる可能性があります。例えば、クラス変数に値を割り当てたり、他のスレッドにアクセスできる変数の例があります。
脱出分析の理論基礎
Jong-Deok Choi、Manish Gropta、Mauricio Seffano、Vugram C.Sreedhar、Sam Midkiffなどに基づいて、論文「Escape Analysis for Java」で説明したアルゴリズムは、逸脱分析を行います。
このアルゴリズムは,連結図を導入して,オブジェクトとオブジェクト参照との間の到達可能性関係を構築し,サブベースで,結合データ・ストリーム解析法を提案する。このアルゴリズムはコンテキスト依存性と流れに敏感であり,オブジェクトの任意の階層の入れ子関係をシミュレーションしているので,解析精度が高く,実行時間とメモリ消費が比較的大きいだけである。
ほとんどのエスケープ分析の実現は「クローズドワールド」の前提に基づいています。実行可能なすべての方法はエスケープ分析をする前にすでに知っています。そして、プログラムの実行はそれらの間の呼び出し関係を変えられません。しかし、実際のJavaプログラムが実行されると、このような仮定は成立しません。Javaプログラムが持つ多くの特性、例えば、ダイナミッククラスのローディング、ローカル関数の呼び出し、反射プログラムの呼び出しなど、いわゆる「閉じた世界」という約束を破る。
脱出分析後の処理操作
脱出分析を経て、対象の3つの可能な逃亡状態を得ることができる。
GlobalEscape(グローバル逸脱):つまり、オブジェクトの引用は、方法またはスレッドから逸脱しています。例えば、オブジェクトの参照は、クラス変数にコピーされたものであり、またはすでに逸脱しているオブジェクトに格納されているもの、または、このオブジェクトの参照は、方法の戻り値として呼び出された方法に返される。
ArgEscape(パラメータレベル逸脱):方法呼び出し中にオブジェクトを転送するアプリケーションを一つの方法に適用します。この状態は調整された方法のバイナリコードを解析して決定できる。
NoEscape(エスケープなし):スカラー置換が可能なオブジェクト。このオブジェクトは伝統的なヒープに割り当てられないことができます。
コンパイラは逸脱分析の結果を使ってプログラムを最適化できます。
スタック割り当ての対象はスタック割り当ての対象となります。一つの方法の中のオブジェクトは、オブジェクトの参照が逸脱していない場合、この方法はスタックメモリ上の非常に見られるスタックメモリ上に割り当てられるかもしれません。
同期をなくす:スレッド同期の代償はかなり高く、同期の結果は同時性と性能を低下させる。逸脱解析は、あるオブジェクトが常に一つのスレッドにしかアクセスされていないかどうかを判断し、一つのスレッドにのみアクセスされると、そのオブジェクトに対する同期動作は、同期保護されていない動作に転化することができ、これによって、合併の度合いと性能を大幅に向上させることができる。
ベクトル代替:逃散分析方法対象のメモリ格納構造が連続して行う必要がないと発見された場合、対象の一部または全部をCPUレジスタに保存することができ、アクセス速度を大幅に向上させることができる。