[seasar-dev:292] [S2Container] パフォーマンス劣化を引き起こす問題発見

Takanori Suzuki szk-micamale @ giga.ocn.ne.jp
2006年 3月 6日 (月) 01:37:53 JST


たかのり@SMGです。

S2Container にパフォーマンス劣化を引き起こす箇所を発見したので、
ひとまず報告します。

長文で申し訳ありません。

【問題点】
 dicon を細かく分割し、include を多用すると、
 コンポーネントの取得に時間がかかる。

【原因】

 あるコンポーネントを取得しようとする際に、以下のような処理に
 なるためです。

 ・include された dicon は線型検索で解析される。
 ・ある dicon が複数個所で include されている場合、
  取得対象のコンポーネントが定義されていなくても、
  include されている分だけ毎回検索される。

 dicon に定義されたコンポーネントは、app.dicon をルートとして、

  1. 取得対象コンポーネントの名前/クラスの component 定義が、
    自分自身にあれば、ComponentDef を返す。
  2. component 定義がない場合は、include されている dicon の
    内容を検索する。
    →複数ある場合は、上に記述されているものから順に検索。

 という順で検索されるようですね。
 →
org.seasar.framework.container.impl.S2ContainerImpl#internalGetComponentDef
   が処理の中心。
 → dicon ファイルひとつに対し、S2ContainerImpl のオブジェクトが1つ生成され
る。

 この際、component 定義は Map による検索になりますが、
 include された dicon 定義を取得する処理は List による検索に
 なります。

 このため、1つの dicon に1つのコンポーネントを定義し、
 それらを include するような記述をすると、
 コンポーネントのヒット率が極端に低くなり、パフォーマンスが劣化します。


【問題事例】

 例えば、S2DaoMaker を利用すると、
 1つのDAOに対して以下のような dicon 定義が出力されます。

 MAuthDao.dicon
 ------------------------------------------------------------
 <components>
     <include path="dao.dicon"/>
     <component class="cx.ath.mof.test.dao.MAuthDao">
         <aspect>dao.interceptor</aspect>
     </component>
 </components>

 ※include されている dao.dicon は、
  さらに j2ee.dicon を include している。
 ※alldao.dicon という dicon で上記の dicon を include している。


 DAOが100個あるとすると、
 alldao.dicon を include した dicon の内容を解析する際に、
 internalGetComponentDef が300回も実行されることになります。
  → 100(Dao) × 3(MAuthDao.dicon → dao.dicon → j2ee.dicon)

 さらに、app.dicon の下に書かれれば書かれるほど、
 取得したいコンポーネントが見つかるまで時間がかかります。
 それより上に include された dicon を全て解析するためです。

 今回、この問題を見つけたプロジェクトでは、
 200超のテーブルがあり、また alldao.dicon を
 数十箇所で include していたこともあって、
 数画面遷移するだけで internalGetComponentDef が
 数百万回実行されるような状況になっていました。


【回避策】

 レイヤー毎など、1つの dicon になるべく多くの component 定義を
 記述し、アプリケーション全体の diconファイル/include 定義が
 少なくなるようにする。


【修正案】

 自分で修正してみようかとも考えたのですが、
 dicon の定義内容を保持する部分であり、
 影響範囲が大きいので、ひとまず辞めました(^^;

 修正する方向性としては、

  ・名前空間毎に component の定義を Map で保持するようにする。
  ・あるコンポーネントを取得する際に、一度検索した dicon 定義は
   二度と検索されないようにする。

 というあたりがひとまず思い付いたところです。

-----
Takanori Suzuki
e-mail: szk-micamale @ giga.ocn.ne.jp
http://d.hatena.ne.jp/szk-takanori/




Seasar-dev メーリングリストの案内