6.6.2 スレッドローカルヒープ
データアクセスの効率化の手法として、最新のJavaVMではスレッドローカルアロケーション技 術が採用されている。この技術は、各々のスレッドに小さなヒープ領域(スレッドローカルヒープ)
を割り当てておき、各スレッドが生成したオブジェクトはスレッドローカルヒープ内に配置するも のである。スレッドローカルヒープへのオブジェクトアロケーションの動作は次のとおりである。
(1)各スレッドは新世代領域の一部をスレッドローカルヒープとして確保する。
(2)各スレッドにおけるオブジェクト生成の際には、排他制御なしにスレッドローカルヒープ(新 世代領域)にオブジェクトを割り当てる。
(3)新世代領域または旧世代領域のガーベジコレクションが起きると、スレッドローカルヒープは 回収される。
(4)ガーベジコレクション終了後、新しいスレッドローカルヒープが各スレッドに割り当てられる。
スレッドローカルヒープ技術は以下の効果を狙っている。
• Javaオブジェクト生成の際に、一貫性を保つため、ヒープの排他制御が必要である。スレッ ド毎に完全にヒープが分かれている場合、スレッドがヒープを占有できることから排他制御が 不要となり、高速にオブジェクトを割り当てることができる。
• 各スレッドは連続したヒープ領域にオブジェクトを配置することができる。Javaオブジェク トを生成するスレッドと、Javaオブジェクトにアクセスするスレッドは同じであることが多 いため、スレッドローカルヒープ内の複数のJavaオブジェクトについては同時期にアクセス する確率が高く、データキャッシュのヒット率が高くなる。
このうち、後者は、データキャッシュのヒット率向上効果を狙ったものであるが、Javaオブジェ クトについて、アクセス頻度の偏りが大きければ、ヒープをさらに分割することでキャッシュヒット 率をより向上させることが出来るのではないかと推測した。
6.7 動的データ配置技術
本論文では、動的データ配置技術(アクセス頻度に基づくJavaオブジェクト配置技術)として、
Javaオブジェクトを、アクセス頻度に応じて別のヒープ領域に割り当てる技術を提案する。以下で 本技術について説明する。
6.7.1 動的データ配置技術概要
頻度別のヒープ領域を用意し、オブジェクトへのアクセス頻度に応じて、Javaオブジェクトを生 成するヒープ領域を変えるのが基本的なアイデアである。
ここでは次のように条件を絞って効果を確認することとした。
• オブジェクトへのアクセス頻度は予め計測しておき、それに基づいた割当情報がVMに渡さ れる。
• ヒープ領域はアクセス頻度の高いオブジェクト(以下、ホットオブジェクト)用とアクセス頻 度の低いオブジェクト(以下、コールドオブジェクト)用の2種類とする。
• Javaバイトコードにおけるオブジェクト割当命令に対し、ホットオブジェクト用ヒープかコー ルドオブジェクト用ヒープかを決める。つまり、同じ命令の箇所で生成されたオブジェクトは 常に片方のヒープに割り当てられる。
• 一度ホットオブジェクト用ヒープに生成されたオブジェクトは、コールドオブジェクト用ヒー プに移動することはない。逆も同様である。
• ガーベジコレクション時には頻度別の扱いは考慮しない。
上記の条件のもと、オブジェクトへのアクセス頻度に基づいて頻度別のヒープにオブジェクトを 配置するための頻度別割当VMを開発した。
6.7.2 頻度別割当の方法
Javaバイトコードのうちオブジェクト割当を行なうのは、次の4種類の命令である。
• new
• newarray
• anewarray
• multianewarray
頻度別割当VMは、次のように、頻度別スレッドローカルヒープへオブジェクトを割り当てる
(図51)。
(1)各スレッドは新世代領域内にスレッドローカルヒープを2個ずつ確保する(頻度別ヒープ)。
一方をホットオブジェクトを割り当てる頻度別ヒープ、他方をコールドオブジェクトを割り当 てる頻度別ヒープとして使用する。
(2)Javaバイトコード中のオブジェクト割当命令に対し、指定された頻度別ヒープへオブジェク トを割り当てる。
(3)ガーベジコレクションでは頻度別ヒープの指定は考慮されない。ガーベジコレクション時に は、スレッドローカルヒープ内に生存しているオブジェクトは、頻度別ヒープの区別なく新世 代領域または旧世代領域へ移動される。
(4)ガーベジコレクション時、各スレッドのスレッドローカルヒープは回収され、新しいスレッド ローカルヒープが割り当てられる。
6.7. 動的データ配置技術 103
for thread B for thread A new
new
hot heap ( thread l oc al ) nursery generation
c ol d heap ( thread l oc al ) thread A
new new thread B
for thread B for thread A hot
c ol d
c ol d mark and sweep
tenure generation
c opy gl ob al
図 51: 頻度別のオブジェクト割付
6.7.3 頻度別ヒープの指定方法
アクセス頻度の解析結果を与えることによって、ホットオブジェクト同士を連続したヒープ領域 に配置することが可能になる。
頻度別割当VMは、起動時に頻度別ヒープを指定するテキストファイル(以下、頻度別ヒープ指 定ファイル)を読み込む。頻度別ヒープ指定ファイルでは、Javaバイトコード中のオブジェクト割 当命令を、Javaメソッド名とメソッドの先頭からのバイトコードのオフセット値の組によって指定 する。各オブジェクト割当命令について、どちらの頻度別ヒープからオブジェクトを割り当てるか を指定することができる。
指定が特にない場合は、頻度別割当VMはホットオブジェクト用の頻度別ヒープを使用する。
頻度別ヒープ指定ファイルが与えられた場合、頻度別割当VMは、VM内に頻度別ヒープ指定情 報を表すデータ構造を保持する。
• インタプリタ実行中の動作
インタプリタによってオブジェクト割当命令が実行されるときは、当該のオブジェクト割当 バイトコードで使用する頻度別ヒープが指定されているかどうかを実行の度に問い合わ せる。
• JITコンパイル後の動作
JITコンパイラ [55, 90] はJavaメソッドの実行頻度の履歴を実行時に取得し、頻繁に実行 されるJavaメソッドをコンパイルして機械語に変換する。JITコンパイル時に、頻度別 ヒープ指定情報の問い合わせを行なうが、その際に機械語として頻度指定のコードを埋 め込む。そのため、JITコンパイル後に頻度別ヒープ指定情報の問い合わせは行なわず、
余分な処理時間は必要としない。
6.7.4 頻度別割当により期待される効果
ここまで説明してきた処理により、ホットオブジェクトは連続したヒープ領域に割り当てられる。
このことによる効果は2つある。
(1)初期参照ミスの減少
初期参照ミス(compulsory miss、cold start miss)とは、キャッシュラインを最初にアクセ スする時に起こるミスである[91]。頻度別割当により、同時に使用されるオブジェクト が同じキャッシュライン内に入る可能性が高くなり、初期参照ミスの減少が期待できる。
(2)競合性ミスおよび容量性ミスの減少
競合性ミス(conflict miss、collision miss)とは、同じインデクスをもつ異なるキャッシュラ インにアクセスすることで起こるミスであり、容量性ミス(capacity miss)とは、キャッ シュしたいライン数がキャッシュ容量を上回ることで起こるミスである[91]。頻度別割当 により、ホットオブジェクトを含むキャッシュラインの入れ替えが減り、競合性ミスおよ び容量性ミスの減少が期待できる。
以降、ベンチマークによる評価により、これらの効果を実証する。