[Java] Testing javac: more, faster

原文はこちら。
https://blogs.oracle.com/jjg/entry/speeding_up_javac_tests#fn2

どれほどJavacのテストを改善してきたか、少なくとも主要なLangtoolsユニットや会期テストスイートの中でどれほど改善したかを見返すのは楽しいものです。
Raising the (langtools) quality bar
https://blogs.oracle.com/jjg/entry/raising_the_langtools_quality_bar
Speeding up tests again: another milestone
https://blogs.oracle.com/jjg/entry/speeding_up_tests_again_more
JDK5、6、7、現在はJDK8の、"最先端"のテストで最近集めたいくつかの数値をご紹介しましょう。これらの数値を対応するJDKビルドの各リリースのjavacのテストを実行して収集しました。各実行において、以下の情報を記録しました。
  • javacテストの数
  • テスト実行の経過時間
  • javacの呼びだし回数(生成されたJavaCompilerオブジェクトの個数を計測)
  • ユニットテスト回数の表示(作成されたContextオブジェクトを計測)
テストはすべて同一のハードウェア(Ubuntuの12.04を実行している中間的な大きさのサーバ)で実施し、その他のジョブはテスト中に同時に走らせていません。jtregの同一バージョンをすべてのテストの実行で使用しました。JDK 5でのテストはjtregの "samevm"で動作するように設定しておらず、そのため、より遅い"othervm"モードで実行しなければなりませんでした(このモードでは、各コンパイルおよびテスト実行で新しいJVMを作成します)。すべてのテストを連続的に実行しました。つまり、jtreg機能を使って同時にテストを実行してはいません。また、これらの実験を任意の特別注意深く制御された科学的な方法で行ったという主張はしません。
Description Notes Release/build 
5u51 6u51 7u25 8-b92
実行モード othervm samevm samevm samevm
経過時間(mm:ss.00) 同一H/W
同一jtreg
08:12.64 03:02.82 05:29.83 12:19.22
%CPU 145% 171% 217% 492%
#javac tests in test/tools/javac/ 845 1140 1705 2436
#compilations #JavaCompiler.<init> 848 1594 41922 381301
#contexts (indicative of unit tests) #Context.<init> 850 1790 271642 591950
テスト1回あたりの平均時間 00:00.583 00:00.160 00:00.193 00:00.303
コンパイル1回あたりの平均時間 00:00.581 00:00.115 00:00.008 00:00.002
テスト1回あたりの平均コンパイル回数 1.00 1.40 24.59 156.53

この数値の意味するところは?

最初(5u51)と最後(8-B92)の列で最も単純な比較をすると、同じハードウェアで、前者に比べて後者は50%余計にテストに時間がかかります。とはいえ、2005年当時には同じハードウェアはなかったのですから、これはいささか不公平な比較でしょう。個人的な思い出を申し上げれば、当時使っていたテストは実行にほぼ30分ほどかかっていました。しかし、たとえテスト実行が50%余分に時間がかかることが許可されていたとしても、その時間で実行できる内容が全く違います…
  • ほぼ3倍のテスト回数(2436 vs. 845)
  • 450倍のコンパイル回数 (381301 vs.848)
  • 以前とは比較にならない、21万回以上のユニットテスト (591950-381301)
5u51 (08:12.64)から6u51 (03:02.82)の経過時間の変化は興味深いもので、このことはothervmモードからsamevmモードへの変更による利得を示しています。
CPU使用率の数値はLinuxのtimeコマンドで取得したものであり、複数プロセッサの可用性を反映しています。JDK 5においてさえも、HotSpotはマルチプロセッサを利用できました。より最新のリリースでの大きな数値はテストがより多くのプロセッサを使用していることを示しています。特にJDK 8でのテストでは。

何をしてきたのか?

改良は多くの要因の結果ですが、これは「より少ない時間で、より多くのことを行うために、End to EndのTLC(Total Landed Cost)」としてまとめられるものです。
以下のリストでこれまでにやってきたことをまとめました。
  • jtregのsamevmモードを修正
  • javacを修正し、テストハーネスで動作するようにした(診断のための特別なテストモードを含む)
  • シェルテストの利用を削減(以下のリンクを参照)
    Shelling Tests
    https://blogs.oracle.com/jjg/entry/shelling_tests
  • 各テストで多くの、時には何千ものテストケースを実行することにより、テストを改善
  • javacインフラストラクチャをできるだけテストケースで共有するようにテストを最適化
  • (同時テスト実行が可能になる)jtregのagentvmモードを追加
  • フックをjavacに追加してよりよいユニットテストを容易に実施
  • 1回のテストで同時にテストケースを実行することにより、最新のハードウェアを活用

今後は?

以前、othervmまたはsamevmモードを使用してサーバー上でテスト実行したと申し上げましたが、サーバーの機能をより活用するため、もう一つ追加のテストを実行しました。この実行では、16のテストを同時に実行することができました。以下の表は、以前の結果で関連するデータと、追加テスト実行の結果得たデータを並べたものです。
Description Release/build
5u51 6u51 7u25 8-b92
実行モード samevm samevm samevm samevm agentvm
同時実行数 1 1 1 1 16
経過時間 08:12.64 03:02.82 05:29.83 12:19.22 2:06.91
%CPU 145% 171% 217% 492% 2198%
16個のテストを並列実行することで大きな高速化を期待されるかもしれませんが、遅いテストがいくつかあった結果、46秒ほど経過時間が延びています。そうしたテストを除けば、残りのテストは、1分23秒で完了していました。この数値をどのようにご覧になるでしょうか。

謝辞

ここで説明する結果は、過去長年にわたって、javacに携わりテストしてきた多くの人々(Maurizio, Brian, Joe, Kumar, Vicente, Alex, Steve, Sue, Sonali, Matherey、JCK-compilerチーム)のおかげです。

0 件のコメント:

コメントを投稿