第 5 章 I-call if 変換の実現
5.1 I-call if 変換が仮定クラスに与える影響
5.2.1 クラスチェック vs. メソッド チェック
ここではまず,クラスチェック変換とメソッド チェック変換が実行速度に与える影響の 定性的な違いについて述べる.次にベンチマークによる定量的な比較結果を示し ,比較結 果について考察する.最後に,考察の結果から,クラスチェック変換とメソッド チェック 変換の使い分け方を提案する.
実行速度に与える影響の定性的な違い
メソッド の候補数lとクラスの候補数kについては,一般にlkが成り立つ.すなわ
ち,メソッド チェック変換の方がクラスチェック変換より分岐回数が少なくなりうる.な ぜなら,メソッド チェック変換では,メソッド の定義を共有する複数のクラスを1回の比
較で特定できるためである.
分岐回数が少なくなりうるならば ,全ての仮想メソッド 呼出しをメソッド チェック変換 で最適化すれば良いかというと,必ずし もそうではないDetlefs99].なぜなら次の例に示
すように,メソッド チェック変換の方が遅くなるケースがあるからである.
レシーバのクラスがほぼ唯一な仮想メソッド 呼出しについて考える.この場合,ク ラスチェック変換を適用してもメソッド チェック変換を適用しても,実行時には最初 の分岐で比較結果が真になり,直接呼出しする経路を辿るケースがほとんどになる.
最初の分岐に至るまでの機械コード を図5.1に示す.図5.1の機械コード を見ると,
メソッド チェック変換の方がロード 命令を2回多く実行するため,遅くなることが 判る.
Java2Cトランスレータでは,図5.1に示した機械コード の差異に加え,最適時に追加
する仮定クラスの違いも実行速度に影響する.5.1 節で述べたように,メソッド チェック 変換の方が追加する仮定クラスが少なく,リンクの遅延から受ける影響が小さい.
ベンチマークによる比較
図5.2に,Java2Cトランスレータで次に示す 3つの方針によって仮想メソッド 呼び 出
しを最適化した場合の実行速度の比較を示す.
1.クラスチェック変換のみ
2.クラスチェック変換とメソッド チェック変換の使分け
3.メソッド チェック変換のみ
クラスチェック変換とメソッド チェック変換の使分けについては,メソッド とクラスの候補 数が同一の場合にはクラスチェック変換を,異なる場合には メソッド チェック変換を用い た.if文におけるクラスやメソッド の比較順序および 比較候補数は,比較順序の違いによ る速度差が生じることを防ぐ ために同一とし た.たとえば クラスチェック変換でCA,CB
の順で比較する場合,メソッド チェック変換ではCA::m,CB ::mの順で比較した.比較
順序は候補メソッド を定義するクラスを読み込んだ順序の通りとし た.I-call if変換は候
補メソッド 数を3以下に限定できる仮想メソッド 呼出しに適用した.クラスチェック変換 では候補メソッド に対応する候補クラスから1つを選んで比較対象とし た.候補クラスの 選択基準は,メソッド を定義するクラスが抽象クラスでなければ定義するクラスとし ,抽
IIBB §§jj¤¤tt||bb~~jjµµ11BB||
j¤t|b~jµ+x~|b~jµ1ö½ j¤t|b~jµ1B
x~|b~jµ1B
¶¶¶¶ººÆÆÄÄÇɼÊÊÇɼÊÊ
¶¶¶¶ÁÁ¼ÊʼÊÊ
¶¶¶¶»¹»¹
¶¶¶¶ÁÁ¸¸Í͸º¸º
¶¶¶¶ÄǼ¾¸Ì»ÄǼ¾¸Ì»
ÀÀÆÆ
¶¶¶¶ÄËÄËÉÉËË
¶¶¶¶ÁÁ¸¸ººÂ ç ç$$
®|
®|··jjÄÄáá
図5.2: 実行速度によるクラスおよび メソッド チェック変換の比較
象クラスならば 候補クラスのうち一番先に読み込んだものとした.限定的I-call if変換と
非限定的I-call if変換の使分けについては,可能な場合には全て限定的I-call if変換を施
した.
図5.2の縦軸はクラスチェック変換のみで最適化したコード の実行速度を100とした場
合の相対的な実行速度を表し ,横軸はSPECjvm98を構成するベンチマーク項目を表す.
図5.2から, 213 javacと 228 jackの2項目で実行速度に差がでていることがわかる.
まず,これらの2項目で差がでた原因を考察し ,次に他の項目で差が出なかった理由を考 察する.
213 javacと 228 jackで差がでた理由 213 javacと 228 jackでは共に,メソッド チェック変換のみで最適化すると実行速度が最も速くなる.最も遅いクラスチェック変換 のみで最適化し た場合と比較し て, 213 javacでは9.8%, 228 jackでは 1.6%高速に
なっている.メソッド チェック変換のみによる最適化では,クラスチェック変換とメソッド チェック変換を使い分ける最適化よりロード 命令を多用する.それにもかかわらず メソッ ド チェック変換のみの方が実行速度が速くなる原因は,追加する仮定クラスの違いにある と考える.すなわち,非限定的クラスチェック変換と非限定的メソッド チェック変換では,
非限定的メソッド チェック変換の方が追加する仮定クラス数が少なく,より早い時期に静 的コンパイル済みコード をリンクしてプログラムの実行を高速化できる.
リンク時期の違いを除去し て静的コンパ イル済みコード の実行速度を比較するため,
全メソッド について静的コンパイル済みコード をあらかじめリンクし てから 213 javac と 228 jackを実行した結果を表5.2に示す.図5.2の実行速度はベンチマークを1回実
行した場合の結果であり,リンク時期の影響を受けるが,4章で述べたようにベンチマー
表5.2: 静的コンパイル済みコード のみによる実行時間 ベンチマーク 最適化 実行回次
項目 方針 1回目 2回目以降 C 334.983 292.167 213 javac H 330.973 292.443 M 304.990 292.664 C 317.040 309.858 228 jack H 316.932 310.213 M 312.038 309.875
※数値は実行時間,単位は秒
※最適化方針の略号C,H,Mは次の最適化方針を表す.
C:クラスチェック変換のみ
H:クラスチェック変換とメソッド チェック変換の使分け M:メソッド チェック変換のみ
表5.3: 仮想メソッド 呼出しにおける誤分岐回数の分布
ベンチマーク 最適化 実行時間 誤分岐回数
項目名 方針 (秒) 0 1 2以上 合計
C 247.250 1,620( 70.6%) 571(24.9%) 102(4.4%) 2,293
201 compress H 247.730 1,730( 75.4%) 461(20.1%) 102(4.4%) 2,293
M 247.638 1,730( 75.4%) 461(20.1%) 102(4.4%) 2,293
C 392.862 20,123,738( 74.8%) 6,771,720(25.2%) 294(0.0%) 26,895,752 202 jess H 395.106 26,892,016(100.0%) 3,442( 0.0%) 294(0.0%) 26,895,752 M 394.909 26,892,294(100.0%) 3,452( 0.0%) 294(0.0%) 26,896,040 C 734.172 14,946,416(100.0%) 3,786( 0.0%) 594(0.0%) 14,950,796
209 db H 737.286 14,947,417(100.0%) 2,785( 0.0%) 594(0.0%) 14,950,796
M 732.726 14,947,418(100.0%) 2,786( 0.0%) 594(0.0%) 14,950,798 C 334.983 14,834,421( 66.5%) 6,211,718(27.8%) 1,268,556(5.7%) 22,314,695 213 javac H 330.973 17,797,120( 77.2%) 5,223,730(22.7%) 39,553(0.2%) 23,060,403 M 304.990 21,225,152( 79.3%) 5,486,978(20.5%) 42,511(0.2%) 26,754,641 C 277.168 440,265( 12.4%) 3,101,643(87.0%) 21,431(0.6%) 3,563,339 222 mpegaudio H 274.814 3,493,138( 98.0%) 70,196( 2.0%) 16(0.0%) 3,563,350 M 275.558 3,493,139( 98.0%) 70,196( 2.0%) 17(0.0%) 3,563,352 C 402.205 168,541,406( 97.5%) 2,875,063( 1.7%) 1,390,708(0.8%) 172,807,177 227 mtrt H 404.065 171,642,879( 99.3%) 1,164,040( 0.7%) 258(0.0%) 172,807,177 M 402.533 171,642,886( 99.3%) 1,164,042( 0.7%) 258(0.0%) 172,807,186 C 317.040 10,389,602( 94.0%) 653,960( 5.9%) 8,840(0.1%) 11,052,402 228 jack H 316.932 10,548,147( 95.4%) 495,415( 4.5%) 8,840(0.1%) 11,052,402 M 312.038 10,665,710( 94.8%) 572,026( 5.1%) 8,840(0.1%) 11,246,576
※最適化方針の略号C,H,Mの意味は表5.2と共通.
クを複数回連続して実行すると,1回目で必要なクラスを全て初期化,リンクしてし まう ため,2回目以降は静的コンパイルコード のみでベンチマークを実行できる.
表5.2から,2回目以降の実行,つまり静的コンパイル済みコード のみで実行した場合 の速度はほぼ 互角といえる.クラスチェック変換を使う方が,ロード 命令の実行回数が少 ない分だけ速くなる傾向は特に観測できなかった.これらのことから,図5.2の実行速度
の差は静的コンパイル済みコード のリンク時期の違いから生じたと考える.
213 javacと 228 jack以外で差がでない理由 213 javacと 228 jack以外の項目で 実行速度に差が出ない原因を検討するための資料として,表5.3に分岐を必要とする仮想 メソッド 呼出しの実行回数を,実行時に誤分岐した回数ごとに分類した結果を示す.ここ
で分岐を必要とする仮想メソッド 呼出しとは,I-call if変換により1段以上のif文を含む
呼出し文に変換したものを示す.nalメソッド 呼出しなど 分岐を必要としないものについ ては,クラスチェック変換とメソッド チェック変換で変換結果が同一なので検討対象から 除外する.また,誤分岐回数とは,I-call if変換後の仮想メソッド 呼出しのコード を実行 する過程で通過するif文において,呼出し対象のオブジェクトのクラスあるいは メソッド を比較した結果が偽となる回数を表す.
表5.3について,分岐を必要とする仮想メソッド 呼出しの実行回数が最も多く,したがっ てI-call if変換の影響を最も受けやすい 227 mtrtに注目して考える.227 mtrtでは,各 最適化方針間で誤分岐の比率に大きな差がない.また,実行回数の合計欄の値がほぼ 同 一なことから,静的コンパイル済みコード のリンク時期にも差がないといえる.これら
が 227 mtrtで実行速度に差が生じないことの原因だと考える.なお,静的コンパイル済
みコード のリンク時期が同一ならば,クラスチェック変換の方がロード 命令の実行回数が 少ない分だけ実行速度が速くなるはずだが,その傾向は観測できなかった.
誤分岐が実行速度に与える影響について, 227 mtrtについておこなった実験から考え る.表5.3から,227 mtrtをクラスチェック変換のみで最適化すると,1度も誤分岐しな
い確率が97.5%になることがわかる.実験のため,クラスチェック変換における比較候補ク
ラスの選択アルゴ リズムを変更し,これを66.4%として差分の31.1%(67,633,955回)を 1回誤分岐した後に間接呼出しで実行するようにしたところ,実行時間が9.02秒余計にか
かった.表5.3から,202 jessをクラスチェック変換のみで最適化すると,1回誤分岐す
る仮想メソッド 呼出しが増えることがわかるが,増加数は6,768,300回程度であり,実行時
間への影響は9:02676768633300955'0:90秒程度と見積もることができる.0.90秒は 202 jess
の全実行所要時間の0.23%と小さな差に過ぎない.また,表5.3から静的コンパイル済み コード のリンク時期にも差がないことがわかり,これらの結果とし て 202 jessでは各最 適化方針間で実行速度に差が出なかったと考える. 201 compressなど 残りの項目につい ては,分岐を必要とする仮想メソッド 呼出しの実行回数自体が少ないために,各最適化方 針間で実行速度に差が出なかったと考える.
クラスチェック変換とメソッド チェック変換の使い分け方
結論として,クラスチェック変換とメソッド チェック変換の比較では,メソッド チェック 変換を用いる方が静的コンパイル済みコード のリンク時期を早めることでプログラムの実 行速度を高速化でき,それ以外の点では大きな差が出ないといえる.