230 likes | 377 Views
アプリケーションに応じた AOP による高速化が可能な 永続システム. 数理・計算科学専攻 千葉研究室 青木 康博 指導教官 : 千葉 滋. SELECT id FROM author t0 WHERE t0.id = 98. 永続オブジェクト・システム. EJB2 など. リファレンスを辿る際に自動的に SQL 発行 データベースを意識する必要がない O/R 間のインピーダンス・ミスマッチを解消 アプリケーションの開発効率を高める. < paper table >. 永続クラス. Josh. 1. 30. ・・・.
E N D
アプリケーションに応じたAOP による高速化が可能な永続システム 数理・計算科学専攻 千葉研究室 青木 康博 指導教官: 千葉 滋
SELECT id FROM author t0 WHERE t0.id = 98 永続オブジェクト・システム EJB2 など • リファレンスを辿る際に自動的に SQL 発行 • データベースを意識する必要がない • O/R 間のインピーダンス・ミスマッチを解消 • アプリケーションの開発効率を高める < paper table > 永続クラス Josh 1 30 ・・・ class Paper { String title Authorauthor; … } class Author { String name; Location location; …. } 2 GlunJ 98 Paper p = …; Author a = p.author ・・・ 自動的なデータ取得 authr_id title id < author table > ・・・ 98 Aoki Tobe 99 ・・・ データベース id name
リファレンスを辿る毎に SQL を発行していては 効率が悪すぎる データベースからの効率よいデータ取得が必要 まとめてデータを取得すれば SQL 発行を最適化出来る E.g.) Author オブジェクトのみを一括して取得したい 高速化の必要性 void showPaperList(List papers) { Iterator it = papers.iterator(); while(it.hasNext()) { Paper p = (Paper)it.next(); Author a = p.getAuthor(); / * p.title と a.name を表示 */ } <RDB> Author を取得 authrs papers 過剰なDB アクセス
Author a0 Author void getGenres(List papers) { while(…) { Paper p = (Paper)it.next(); Genre g = p.getGenre(); ….}} Genre a1 g0 Author Genre a2 g1 Genre 過剰な DB アクセス g2 void showPaperList(List papers) { Iterator it = papers.iterator(); while(it.hasNext()) { Paper p = (Paper)it.next(); show(p);}} 過剰なDB アクセス 高速化のためのカスタマイズ例 • 効率よくデータを取得したい • 今後利用されるデータを先読みし、まとめて取得したい • 処理内容に応じて先読みするデータをカスタマイズ List papers Paper p0 Paper p1 Author ではなく Genre を取得 Paper p2 <RDB> authrs Author を取得 papers
Genre を取得 Author は不要 従来のオブジェクト指向による クラスごとのカスタマイズ • 効率のよいデータ取得が実現出来ない • 過剰な DB アクセスをなくそうとすると、不必要なデータを大量に取得してしまう void getGenres(List papers) { while(…) { Paper p = (Paper)it.next(); Genre g = p.getGenre(); ….}} class Paper { String title; …} @FETCH Author author; @FETCH Genre genre; Genre genre; 過剰なDB アクセス void showPaprList(List papers) { Iterator it = papers.iterator(); while(it.hasNext()) { Paper p = (Paper)it.next(); show(p);}} <RDB> Author を取得 Genre は不要 authrs papers
アスペクト指向による高速化を支援する永続システムアスペクト指向による高速化を支援する永続システム アプリケーションの文脈に応じたクラス横断的なカスタマイズ リファレンスの辿られ方に応じて最適化の指示を変更できる 最適化の指示をアスペクトとして分離 徐々に最適化の指示を追加できる 最適化の 指示 提案: AspectualStore の開発 showPaperList(List) { … } Proceeding Author Paper List papers prc ownr p0 p0 getGenres(List) { … } p1 Paper Genre p0 gnr p2
永続システム: AspectualStore • アスペクト指向による高速化を支援 • コード量: 18,000 行程度 • 外部企業が現在デモアプリを AspectualStore 上で 開発中 • より大規模な実験を行う予定 <デモアプリ>
アスペクト記述 class PrefetchDefine { @before(“{Persistable p = $1; Loader l = $1.getBody().getLoader(); l.addFetch(“author”); l.load(); }”) Pointcut p1 = Pcd.call(“showPaperList(..)”); @before(“{ Persistable p = $1; Loader l = $1.getBody().getLoader(); l.addFetch(“author”); l.load(); }”) Pointcut p2 = Pcd.call(“getGenres(..)”); } • メソッド処理ごとのデータ取得の指示 showPaperList() に対する最適化 ・ Author オブジェクトを先読み getGenres() に対する最適化 ・ Genres オブジェクトを先読み
Location Author a 1st iteration : リファレンスの辿り方を収集 name title 2nd iteration : papers 先読みの指示を出す Author a ・・・ name title それ以降の DB アクセスは 発生しない! Author a name 先読みすべきデータを動的に決定するアスペクトも可能 • どのようにリファレンスが辿られるかを検出 • リファレンスの辿られ方がわかりにくい場合 • 最適化の指示をまとめて記述したい場合 void showPaprList(List papers) { Iterator it = papers.iterator(); while(it.hasNext()) { Paper p = (Paper)it.next(); show(p); …}} papers Paper p0 title Paper p1 Paper p2 ・・・
アスペクト記述: GluonJ @Gluepublic class PrefetchDefine { /* Context の定義 */ @Refine static class ContextDefine extends Context { Set loadedFields = new HashSet(); int depth = 0; } /* DB アクセスを引起したパスの格納 */ @Before(“{ // フィールド名を格納}") Pointcut pc = Pcd.call("...PersistentEntity#load*(…)"); /* prefetch 定義 */ @Refine static class IteratorDefine extends PersistentIterator { public Object next(Context cxt) { if(context.hasLoadedFields()) // context の内容を先読み super.next(cxt); }} Context クラスに DB アクセス履歴を格納するためのフィールドを定義 papers に付加された Context に showPaperList() 内で DB アクセスを 引き起こしたフィールドのパスを追加 Iterator.next() を拡張して、 本来の処理の前に先読み処理を追加
アスペクトによる最適化の支援 • 既存の永続システム + AOP だけでは不十分 • 最適化の指示に煩雑な記述が必要 • リファレンスの辿られ方を管理する必要がある • アスペクト内からアプリケーションの文脈を利用出来ない • AspectualStore が提供する主な機能 • 最適化を行ための API • 永続オブジェクト(コレクション) への最適化の指示 • アプリケーションの文脈を格納するための機構 • アスペクトからアプリケーションの文脈を利用可能 • Tomcat からのロードタイム・ウィービング • アスペクトのウィーブ / アンウィーブの手間を削減
<Hibernate によるデータ取得の記述> “FROM Paper FETCH p.title LEFT JOIN FETCH p.author.. WHERE t0.prc_id = 98” journl 著者X’ 著者P’ 著者Q’ 最適化を指示する API • 永続オブジェクトに直感的に指示が出せる API • 直接 SQL を記述するのは煩雑すぎる • 外部キーの名前と値が必要 • 記述すべき SQL はリファレンスの辿られ方によって異なる author.name と title を取得 <データベース> prc_id PK title List papers 98 Proceeding 98 Paper X prc 98 Journal name Paper P paperテーブル jrl PK name Paper Q name Genre gen name authorテーブル
PK 5 journl 著者X’ proceeding テーブル 著者P’ 著者Q’ 最適化を指示する API • 発行する SQL はリファレンスの辿られ方によって異なる author.name と title を取得 Proceeding List papers prc Paper X Journal Paper P journl <Proceeding から 取得された場合> Paper Q “FROM Paper FETCH p.title LEFT JOIN FETCH p.author.. WHERE t0.prc_id = 5” PK prc_id jrl_id 5 1 18 2 5 3 5 4 PK <Journal から取得された場合> 18 5 6 18 “FROM Paper FETCH p.title LEFT JOIN FETCH p.author.. WHERE t0.jrl_id = 18” paperテーブル 18 journal テーブル
journl 著者X’ 著者P’ <AspectualStore> 著者Q’ loader.addFetch(“title”); loader.addFetch(“author.name”); loader.load(); 最適化を指示する API • 永続オブジェクトに直感的に指示が出せる API • 直接 SQL を記述するのは煩雑すぎる • 外部キーの名前と値が必要 • 発行する SQL はリファレンスの辿られ方によって異なる author.name と title を取得 <データベース> PK title List papers Paper X ・データベースに関する作業を 意識する必要がない ・外部キーの名前や値 ・どのようにリファレンスを辿ってきたかを AspectualStore が内部で管理 (後述) Paper P paperテーブル PK name Paper Q authorテーブル
アプリケーションの文脈を格納 • 文脈を格納するための機構 • アスペクトからアプリケーションの文脈を利用したい • メソッド内でどのようなリファレンスが辿られるか • SQL を発行するためには、親オブジェクトが必要 • 既存の永続システム + AOP では不十分 • 時間的に素なデータ・アクセスの取得は困難 • refine や cflow を駆使した煩雑な記述が必要 • 永続オブジェクトは何度も再利用される • 単純に親への参照を持たせるだけでは不十分 [’05 Awais ら] List papers Proceedng prc Paper p0 Location Author a title name Paper p1 Journal j ・・・
アプリケーションの文脈を利用可能 • 永続オブジェクトに Context オブジェクトを付加 • Context クラスを拡張 => アプリケーション文脈を管理 • Context: リファレンス毎に新たに生成 • キャッシュ: 何度も再利用される E.g.) 論文X => 学会Wから参照 論文X’=> 著者Aから参照 Set 学会W 論文P <モデル> <キャッシュ> author papers 著者A 論文X 論文Q Paper PersistentEntity • entity • context • values • state 論文X’ 共有 個別 <文脈情報> 個別 キャッシュ Context Contxt Contxt • 親コンテキストへの参照 • 親コレクションへの参照 title=“aop” year=1999 親: 学会 親: 著者A
ロードタイム・ウィービング • ウィーブ/アンウィーブにかかる手間を削減 • AspectualStore への拡張を JAR ファイルに反映させる必要なし • Tomcat 用のクラスローダを実装 <アプリケーション起動時> 永続クラスへのバイトコード変換 ・ 永続化処理の追加 (リファレンスが参照された 際の SQL 発行) ・ Context クラスの追加 <クラスのロードタイム時> アスペクト記述の反映 Common CL Shared CL Catalina CL WebApp CL ASClassLoader
Paper p3 AOP AOP Paper p6 AspectualStore による最適化の得失 • アプリケーションの挙動を変える最適化はできない • 誤った最適化指示は無視される • JDBC で直接指示する程の最適化は出来ない 例) 主キーは必ず取得 Proceeding prc = …; List papers = prc.getPaprs(); for( Paper p : papers) { if(p.getGenre().equals(“AOP”) { // show Paper details. }} Proceeding papers prc Paper p1 PK genre AOP 1 AOP 2 3 AOP 4 5 Paper p4 6 Expression exp = ExpFactory.eq(“genre”, “AOP”); loader.add(exp); AOP paperテーブル
時間・DBアクセス・メモリ量の比較実験 文献検索システム • 既存の永続システム • オブジェクト指向によるクラス毎の最適化 • AspectualStore • アスペクト指向による文脈に応じた最適化 • SQL 直書き • JDBC を直接利用してほしいデータを指示 Bibliography year journals proceedngs Proceeding Journal name intro name vol papers papers Paper title abstract content Genre genre name author サーバ:P4 Xeon 3.06G, 2GB, PostgreSQL 7.4.2 DBサーバ:Linux 2.6.7 アプリケーションサーバ:Mac OSX Tomacat 5.5, Java 1.5 LAN 1000 BaseTX papers Author Location location name age country town
実験結果 括弧内は主キー と 外部キーを除いた値 DB 通信 (回) 取得データ 数 (個) 実行時間 (秒) オブジェクト 生成 (個) • 既存の永続システムに比べて大幅な速度向上を確認 • DB 通信回数 / 取得データ数の削減 • オブジェクト生成数は同等 3.48 43 381 2528(1522) 既存永続システム AspectualStore 2.46 8 381 759(289) 30%向上 SQL 直書き 2.16 6 181 471(287) 38%向上 予備的な実験 においては…
SQL 直書きとリファレンス参照の併用 リファレンス参照は従来同様、非効率 高速な参照が必要なときは SQL を直接書く AspectualStore ではSQL ではなく高速化のヒントを記述 最適化コードが元のプログラムに混在 関連研究1:O/R mapper • Hibernate • Cayenne • Torque • … String query = “FROM Proceeding p LEFT JOIN FETCH p.papers LEFT JOIN FETCH p.papers.author WHERE …”; // ルート・オブジェクトの取得 Proceeding p = s.createQuery(query).load; List<Papers> papers = p.getPapers(); showPaperList(papers); 利用されそうなオブジェクトを ルート・オブジェクトに含める
関連研究2:自動的な最適化 • アスペクト記述が必要ない • Context-cotrolled prefetch[Philip at al. ‘99] • データベースのアクセス・パターンを基に最適化 • AUTOFETCH [Ali et al. ‘06] • プロファイリングによる最適化 • PrefetchGuide [Wook-Shin et al. ‘03] • 実行時のアクセス・ログによる動的な最適化 • AspectualStore • 手動できめ細かな最適化 • メソッド処理などのオブジェクト以外の文脈も利用可能 • 性能テストをしながら徐々に最適化が可能
まとめ • AOP を利用して高速化が可能な永続システム: AspectualStore の開発 (コード量: 約18,000 行) • アプリケーション文脈に応じた最適化が可能 • クラス横断的な処理を AOP でモジュール化 • クラス毎の最適化指示だけでは不十分 • AOP による最適化を容易に実現する構造を用意 • 永続オブジェクトへ指示を出すための API • アプリケーションの文脈を格納するための機構 • ロードタイム・ウィービング