たぷつきません

おなかがでてきた。もうたぷついてるやん。

メモリリーク

 S2TestCaseでテストケースごとに使用メモリが増えて、どんどん遅くなり最後は固まるという現象が起きた。現行プロジェクトの開発メンバー3人がかりでいろいろ調査したところS2自体S2Daoメモリリークしていることが判明。もろ循環参照で、S2ContainerImplのdestroyでは全く解放されない。S2ContainerImpl,S2ComponentDefImpl,MetaDataDef,AOPなんたらクラスなどの間で循環参照が起きているので1つ1つ解きほぐす必要が。2ちゃんでも比較的最近(2006/05/01)メモリリークの問題が書かれているようだが、議論にもなっていない。2ちゃんだからガセ扱いされてしまっているのではないだろうか。実は対策は進んでいるのだろうか。昔からこうだったのだろうか。と疑問は尽きない。
 destroyというきっかけは提供されているのだからコアの4〜5クラス程度の修正で対策は可能に見える。ただあくまでも「今日ざっくりと追ってひとまずS2ContainerImplへパッチをあてていったところでは」の範囲での話。最も中心のところでこれでは全体の設計としてメモリリークが考慮されていない可能性が高いと思われるので、1つ潰してはまたその次が出現しそうだ。HotDeployといった機能も提供しているのだから、正しくリロードできないのは結構致命的ではなかろうか。まずは開発プロジェクト内で対策して、どこかのタイミングで、seasar2 projectにフィードバックできるのではないかと思う(もちろんその前にバグフィックスされたものがリリースされるほうが助かるのだが)。
 heap_diagnosticsでリークを追っていて気づいたのだが、Containerインスタンス1つにつきServlet系のスコープ全てが立ち上がる。1ダイコン辺りで1Containerが出来てその度に付随するオブジェクトインスタンスが1セット出来る。現行プロジェクトではダイコンの数が多かったのでものすごいインスタンス数になっていた。これらのスコープ用オブジェクトは、1ダイコンごとでは使用しない可能性の方が高いと思われるので、ServletContext,Request,ResponseのスコープはLazyにインスタンス化するのが望ましいだろう。現状はパフォーマンス的に良い実装ではない。
 道理でWebアプリのリロードでOutOfMemoryになるわけだ。リリース後に発覚するなんてことがなく開発中の段階で気づけたことは結果的に良かった(といってもこれまで過去にリリースしたものはアウトなわけだが)。