290 likes | 407 Views
効率的な Java Dynamic AOP システムを実現する Just-in-Time weaver. 佐藤芳樹 千葉滋 東京工業大学大学院 情報理工学研究科. 【発表のあらまし】 効率的な Java Dynamic AOP システム を実現する手法を提案 AOP: アスペクト指向プログラミング 提案手法を実装した Wool を説明. [ BookShelf ] Book search(String key) { Logger.info( “ in BookShelf#search() ” );
E N D
効率的なJava Dynamic AOPシステムを実現するJust-in-Time weaver 佐藤芳樹 千葉滋 東京工業大学大学院 情報理工学研究科 • 【発表のあらまし】 • 効率的なJava Dynamic AOPシステム を実現する手法を提案 AOP:アスペクト指向プログラミング • 提案手法を実装したWoolを説明 PRO-2002-4, Nagoya
[ BookShelf ] Book search(String key) { Logger.info(“in BookShelf#search()”); while (_booklist.hasMoreElements()) if (_booklist.next().match(key)) return book[i]; Logger.info(“out BookShelf#search()”); } [ BookShelf ] Book search(String key) { while (_booklist.hasMoreElements()) if (_booklist.next().match(key)) return book[i]; } [ BookShelf ] Book search(String key) { Logger.info(“in BookShelf#search()”); while (_booklist.hasMoreElements()) if (_booklist.next().match(key)) return book[i]; Logger.info(“out BookShelf#search()”); } [ BookShelf ] Book search(String key) { while (_booklist.hasMoreElements()) if (_booklist.next().match(key)) return book[i]; } Aspect Aspect あちこちに散らばるコード crosscutting concern searchとmatchの前後 Logger.info(…) searchとmatchの前後 Logger.info(…) どこかで無限ループしてるからメソッドの出入りをロギングしてみよう!! [Book] boolean match(String key) { if (match0(key)) return true; else return false; } [Book] boolean match(String key) { Logger.info(“in Article#match()”); if (match0(key)) { Logger.info(“out Article#match()”); return true; } else { Logger.info(“out Article#match()”); return false; } } [Book] boolean match(String key) { Logger.info(“in Article#match()”); if (match0(key)) { Logger.info(“out Article#match()”); return true; } else { Logger.info(“out Article#match()”); return false; } } [Book] boolean match(String key) { if (match0(key)) return true; else return false; } 分散、同期、セキュリティ トランザクション、etc… ロギング処理をプログラム と別に記述 weaver アスペクトとプログラムを 静的に合成(weave) 0. AOP(Aspect-Oriented-Programming) アスペクト指向とは • モジュール間にまたがる横断的関心事(crosscutting concerns)をアスペクトとしてモジュール化 PRO-2002-4, Nagoya
1. 研究の背景 Dynamic AOPとその利点 • アスペクトとプログラムを実行時に合成するDAOPが注目されている 1.開発サイクルの高速化 1.down 3.restart 2.rebuild (recompile,reweave) 要求、環境に応じサービスを 動的にカスタマイズ 1.dynamic weave アプリケーションを止めずにロギングのon/off やパッチ当て 分散GUIアプリケーション ・配置 ・解像度 ・ビットレート ・色数 etc… aspects 2.適応的なサービスアスペクト PRO-2002-4, Nagoya
2. Dynamic AOP AOPを実現するモデル ・フィールド アクセス join-pointでアドバイスを実行する 適切に定義された コードの断片 実行フロー上のポイント ・メソッド 呼び出し ・オブジェクト 生成 Dynamic Join Point Model (AspectJ[*1]で提案) ・・・ アスペクト pointcut場所の指定 (join-pointを指定) match() search() advice処理の記述 join-point Logger.info() *1 Xerox Corporation. “The AspectJ Programming Guide. Online Documentation”, 2001. http://www.aspectj.org/ PRO-2002-4, Nagoya
do_before_advice(); 挿入された フックコード do_after_advice(); do_before_advice(); do_after_advice(); フック 2. Dynamic AOP フックによる典型的な実装 • アスペクトとプログラムの合成 = 静的コード変換によるフック挿入 • join-pointにあたる場所にフックを挿入 • フックにより実行がインターセプトされ適切なアドバイスを実行 join point pointcut 指定 PRO-2002-4, Nagoya
2. Dynamic AOP 既存のJava DAOPシステム • DAOPシステムを実現するためには、実行時にフックを挿入する機能が必要 • 動作リフレクション(演算を横取りし変更できる機能) • CLOS、Smalltalk、etc • 処理系の改造 • 可搬性を損なう • 静的コード変換 • 低品質のコードを生成 → 次に説明 PRO-2002-4, Nagoya
2. Dynamic AOP 静的コード変換 • すべてのjoin-pointへ静的にフックを挿入 • 静的にフックを挿入する場所を特定できない • アドバイスを実行するかどうかをチェック • チェックのための分岐、無駄なフックに よるコードサイズの肥大化 • 常にすべてのjoin-pointでチェック • 低品質のコードを生成 • 長時間稼動するサーバアプリに問題 need_advice(); need_advice(); need_advice(); need_advice(); pointcutでの 指定はここだけ need_advice(); need_advice(); need_advice(); need_advice(); need_advice(); need_advice(); need_advice(); need_advice(); PRO-2002-4, Nagoya
3. ジャストインタイム・フック埋め込み ジャストインタイム・フック埋め込みの提案 • フックを挿入するためにデバッガによる手法と動的クラス書き換え手法をハイブリッド 1.デバッガによるフック挿入・実行(PROSE[*2]) • フックをbreakpointとして挿入 • デバッガがアドバイスを実行 2.動的クラス書き換え(我々が開発) • コード変換でフックを挿入+ロード済みクラスの再定義 • 再定義を可能な限り遅延 *2 Andrei. P, Thomas. G and Gustavo. A. “Dynamic Weaving for Aspect-Oriented Programming” In AOSD’02 PRO-2002-4, Nagoya
3. ジャストインタイム・フック埋め込み デバッガによるフック挿入・実行 • フックをbreakpointで挿入(PROSE[*2]) • breakpointで実行をインターセプト+アドバイス実行 • 実行コードに無駄なフック無し • JPDA(デバッガ)を使用し可搬性を損なわない breakpointセット デバッガが アドバイス実行 デバッガ デバッガ do_advice(); *2 Andrei. P, Thomas. G and Gustavo. A. “Dynamic Weaving for Aspect-Oriented Programming” In AOSD’02 PRO-2002-4, Nagoya
3. ジャストインタイム・フック埋め込み 動的クラス書き換え • フックをコードに埋め込む • 必要になるまで遅延し、Just-in-Timeに埋め込む • 無駄なフックを挿入しない • その後は高速にアドバイスを実行 • HotSwap機能を使用(Sun JDK1.4 JPDA) • デバッガの制御下でロード済みクラスを再定義できる機能 JVM JPDA ロード済み クラス do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); フック入り クラス do_advice(); do_advice(); クラス再定義 PRO-2002-4, Nagoya
3. ジャストインタイム・フック埋め込み ハイブリッドした手法 • 二段階のフック埋め込み • 初めにフックはすべてbreakpointとして挿入 • 選択的に動的クラス書き換え ③-1 デバッガが アドバイス実行 デバッガ デバッガ ① アスペクトがweave しjoin-pointが判明 do_advice(); ② 指定されたすべてのjoin-pointへbreakpointをセット ③-2 動的クラス書き換え 対象プログラムが アドバイス実行 do_advice(); do_advice(); do_advice(); デバッグモード(-Xdebug) でHotSpot実行 do_advice(); PRO-2002-4, Nagoya
3. ジャストインタイム・フック埋め込み ハイブリッドする必要性 • 使用頻度の高いアドバイス • デバッガがアドバイス実行 → アドバイス実行がボトルネック • 使用頻度の低いアドバイス • 高価な動的クラス書き換え → 変換がボトルネック トレードオフ デバッガ アドバイス実行時間 標準でデバッガがアドバイス実行 ハイブリッド システムロードに応じ効果的に 動的コード書き換え 動的クラス書き換え フック埋め込み時間 PRO-2002-4, Nagoya
3. ジャストインタイム・フック埋め込み JITコンパイラとの比較 • JITコンパイラの動作との類似点・相違点 • 類似点 • オンデマンドにコード変換 • 性能向上のために2種類の実行法をハイブリッド • 相違点 • weave後にコードのセマンティクスが変更 =>weave時にactiveなフレームへの配慮が必要 • 実行の途中で書き換えられるメソッドでのアドバイス • 依存関係のあるアドバイス PRO-2002-4, Nagoya
do_advice(); 3. ジャストインタイム・フック埋め込み 実行途中で書き換えられるメソッド • activeフレームではデバッガがアドバイス実行 • HotSwap時にactiveなフレームが参照するクラスは変更されない(JPDAの仕様) activeフレーム= 実行途中のメソッド アドバイスが実行されず一貫性が崩れる weave後に積まれる フレームは変更後の クラスを参照 do_advice(); do_advice(); Book#match0() Book#match() BookShelf#search() クラス定義は元のまま PRO-2002-4, Nagoya
3. ジャストインタイム・フック埋め込み 依存関係のあるアドバイス • activeフレームでのデバッガのアドバイス実行の有無は手動で選択 • beforeアドバイスは実行されていない • afterアドバイスの実行はユーザが選択 例: searchメソッドの前後で時間を計り検索時間を測定する機能を アスペクトで追加 before デバッガ after Book#match0() beforeが実行されてい なくてもafterのみ実行 デバッガ Book#match() BookShelf#search() after PRO-2002-4, Nagoya
3. ジャストインタイム・フック埋め込み 全体の流れ • join-pointでアドバイス実行手法を選択 = 動的に切り替え → 各問題を解決 デバッガに よる実行 デバッガに よる実行 activeフレーム 選択的に 実行 ボトルネックの除去 アドバイス間 に依存関係 do_advice(); do_advice(); 埋め込まれた アドバイス実行 do_advice(); do_advice(); 動的クラス 書き換え do_advice(); do_advice(); activeフレーム アドバイスが 実行されない PRO-2002-4, Nagoya
4. Wool Woolの実装 • ジャストインタイムフック埋め込みをJava用に実装したJust-in-Time weaver • JPDAでbreakpointセットとクラス再定義、Javassistでバイトコード変換 クラス再定義 aspects Javassist do_advice(); do_advice(); + JVM JPDA バイトコード 変換 breakpointセット、 アドバイス実行 Wool PRO-2002-4, Nagoya
4. Wool Woolの起動法 • 外部プログラムから起動 => 開発サイクルの高速化 • アプリケーションが起動 => サービスアスペクトの実現 % wool –weave LoggingAspect –address islisp.ysk.csg.private % wool –unweave LoggingAspect –address islisp.ysk.csg.private WlAspect pda = WlAspect.forName(“PDAAspect”); WlAspect pc = WlAspect.forName(“PCAspect”); Wool wool = Wool.connect(“somedomain”,5432); switch(client) { case PDA : wool.weave(pda); case PC : wool.weave(pc); } PRO-2002-4, Nagoya
4. Wool アドバイス実行手法選択の記述 • アスペクトプログラムからWoolを制御する機構 • コンテキストに応じてアドバイス実行手法を選択 • 外部からweaveする場合、反映されるタイミングが不定 • Woolの初期化 • 合成の前後 • 切り離しの前後 コールバックメソッドに各タイミングで Woolを制御するコードを記述する 例 public void beforeWeave(Wool wool) { if (wool.joinMethodExit()) wool.skip(); } public void afterWeave(Wool wool) { if (wool.countActiveFrame() > 0) wool.regardActiveFrame(); } メタな処理(実行フロー外のポイント)なのでjoin-pointでは表現しない PRO-2002-4, Nagoya
5. 性能測定 比較実験 • 実験環境 Arch : SunBlade1000、 CPU : UltraSPARC-III 750MHzX2、Memory : 1GB OS : Solaris8 JVM : Sun J2SDK1.4.0 HotSpotTMClient VM • Wool 現在は最初のjoin-pointで必ず動的クラス書き換え • 実験プログラム • SpecJVM98のjess • 自然数の和を求める再帰メソッド PRO-2002-4, Nagoya
5. 性能測定 結果と考察(1) 目的-実行時間と合成処理にかかる時間の測定(activeフレーム処理無し) 方法-ナンバーパズル〈N〉、モンキーバナナ〈M〉 〈1〉protectedメソッド(4of146、734615回呼び出し)にnullアドバイス 〈2〉1つのメソッド(1of146、1338回呼び出し)にnullアドバイス 結果 考察 ・アドバイス実行回数が多いほど良い結果、少ないほど動的クラス書き換 えのオーバーヘッド ・join-point抽出+変換再定義を差し引いた実行時間がAspectJに近い 5回計測の最小値 単位[msec] PRO-2002-4, Nagoya
5. 性能測定 結果と考察(2) 目的-デバッガでのactiveフレーム処理の性能劣化 方法-sum()実行中にnullアドバイスをweave activeフレームの個数を変化 結果 26000 2500 考察 ・デバッガでのアドバイス実行回数が多いほど性能劣化 ・扱うactiveフレームが0の場合性能劣化がだいぶ小さい PRO-2002-4, Nagoya
6. まとめ まとめと課題 • ジャストインタイム・フック埋め込みを提案し、Java用のweaverであるWoolをJavaで実装した • 実行時に無駄なフックの無い良質のコードを生成 • アスペクトと合成後に高速実行 • weaverを柔軟に制御する機能を提供 • 今後の課題 • 追加実験(静的コード変換) • 未実装機能の実装(Introduction,aroundアドバイス) • パフォーマンスチューニング • 動的プロファイラの実装 PRO-2002-4, Nagoya
7. 別の実装手法 別の実装手法1 • アドバイス実行方式の選択を自動化 • 手動選択(現在) • アドバイス実行方式を手動で選択できる機構 • 自動選択 • 環境(システムロードなど)に応じ適切な実行方式を選択 • HotSpot技術のように動的プロファイラで実行時の傾向をプロファイリング アドバイスの実行回数が閾値を超える => 動的クラス書き換えを施す PRO-2002-4, Nagoya
7. 別の実装手法 別の実装手法2 • 自己反映的なOpenJITで実装 • アスペクトのディレクティブでコンパイルコードを変更 • 動的に再コンパイル • メソッド単位でアスペクトの合成 • 無駄なフックの挿入をより抑えられる • 同様のactiveフレーム対応処理 さらなる高速化が期待できるが可搬性を 損なうので現実的ではない PRO-2002-4, Nagoya
付録 アスペクトの記述 Javaでのアスペクト記述 public class LoggingAspect extends WlAspect { WlCrosscut record = pointcut("*","BookShelf","search", "(Ljava/lang/String;)V").joinCall(); public void doit() { teach(new WlBeforeAdvice(record) { public void advice(TargetInfo tinf) { Target t = tinf.getTarget(); Logging.info(“in ” + t.className()+”#”+t.name()); } }); } public void initWeave(Wool wool) throws Exception { wool.filter(" ^java.*|^sun.*“,false); } } ポイントカット 記述 アドバイス 記述 weaverの 制御記述 PRO-2002-4, Nagoya
付録 デバッガによるフック挿入・実行 do_advice(); PRO-2002-4, Nagoya
付録 動的コード書き換え do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); PRO-2002-4, Nagoya
付録 ジャストインタイム・フック埋め込み(ハイブリッド) do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); do_advice(); PRO-2002-4, Nagoya