Q: AspectJの実行時のパフォーマンスは悪い?

AspectJ ではソースコードの各地点に プログラムコードを生成するようですが, その結果として,手で各所にコードを書いてた場合よりも 実行時の速度は遅くなるのでしょうか.

A: 場合による.通常,手で書くよりは少し遅い

AspectJ 1.2 で,コンパイラが大幅改良され, パフォーマンスのオーバーヘッドはかなり小さくなりました (以前のバージョンではほぼ確実に「遅い」と答えざるをえませんでした).

手で最適化されたコードを記述した場合に比べ, 通常はアスペクトで書いたコードのほうが遅くなります. ただし,悪いといっても通常は10〜20%といった程度の範囲で, 何倍も遅くなる,ということはありません.

手動で,あちこちに分散して記述したコードは,保守性を悪化させます. そのプログラムにおいてパフォーマンスが最優先事項である場合は 仕方ありませんが,それ以外の場合, 必ずしもアスペクトがボトルネックになるとは限りません.

AspectJ がパフォーマンスを悪化させる可能性

AspectJ を用いたパフォーマンス悪化要因は, 「現在どこを実行しているか」を表現する thisJoinPoint オブジェクトへのアクセス, および実行コンテキストである cflow ポイントカットの使用です.

thisJoinPoint へのアクセスのうち, 特に getSignature や getSourceLocation などによる位置情報の取得, 文字列表現の取得 toString は,getClass().getName() のような 実行コストが比較的高いメソッド呼び出しを含んでいます.

ただし,それもどのくらいの頻度でそのアスペクトが実行されるかに依存するので, プロファイラなどによるパフォーマンスの検証が必須と考えたほうがいいと思います.

一方で,cflow ポイントカットは, メソッドの呼び出し関係を,アドバイスの実行条件として使います.

cflow ポイントカットは,ソースコードとして展開されるとき, メソッド呼び出しごとにスタックに情報を乗せていく (そしてメソッド終了時にスタックから情報を取り除く)ことで 現在実行中のメソッドを把握するコードとなります. そのため, メソッド呼び出しが頻繁に起こる部分で cflow ポイントカットを利用すると, 著しくパフォーマンスを悪化させる可能性があります.

ただし,この問題も,呼び出し関係をコンパイル時に解析することにより, スタックへ情報を追加・削除する処理の配置を必要最小限とすることで 徐々に解決されつつあります.

パフォーマンス vs. 保守性

アスペクト指向の元々の発端として,保守性は大事だ,という話があります.

Gregor Kiczales らの AOP の論文では, 「純粋にオブジェクト指向だけを追求してがんばった良い保守性のコード」と 「画像のキャッシュとかをしてメモリ消費量を削減するアスペクト」を 組み合わせると, 「手動で記述した保守性の悪いコード」に比べると 実行速度では多少負けるが,コード量は大幅に小さくなり, 保守性も高いということを示しています.

実際の数値としては,AOP 実装だと768行,手書きバージョンは 35213行となったそうです. 手書きのバージョンでは,他の関心事のコードと, 今書いているコードというのが混ざり合ってしまい, 保守する際には一度それを解きほぐしてから混ぜなおす作業が 必要であり,それは非常に困難な作業である,と言及されています.

Gregor Kiczales, John Lamping, Anurag Mendhekar, 
Chris Maeda, Cristina Videira Lopes, Jean-Marc Loingtier, John Irwin:
Aspect-Oriented Programming.
Proceedings European Conference on Object-Oriented Programming, 
pp.220-242, 1997.


トップ   差分 バックアップ リロード   一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2004-10-08 (金) 12:04:09 (5100d)