ComboBox のドロップダウンリストを表示するとメモリリーク… のつづきのつづき
Monday, 10. August 2009, 13:13:11
だいぶ遅くなりましたが、ComboBox のドロップダウンリストを表示するとメモリリーク… のつづきのつづきです。
自分たちのビルド手順の問題で、パッチが当たっているはずの Flex のバグが治ってませんでした。というのが前回まで。Flex プロファイラで Flex モジュールのインスタンス数を追いかけても、ちゃんと解放されている様子。
でもって「何をもって、メモリリークが解消されたことの証明にするか」という議論になりました。SDK-18268 以外、自分達の書いたコードに解放漏れはありません、と断言できる資料が作れないとお客さんに説明出来ないよね、って話です。コミットチャージの推移? IE の Private Bytes の推移? Flex プロファイラが報告するメモリ使用量 or インスタンス数?
OS や IE のメモリ使用量はあまりあてにならないだろうと、Flex プロファイラの情報でやることに決まり、大測定大会が始まりました。
これが悪夢の始まり。
よくよく見ると、Flex プロファイラの情報が???だらけなんです。。
そしてとどめが
「被参照数が 0 のインスタンスが残ってる、しかも大量」
というもの。
どうやら Flash Player は、いくら GC を動かしても、以下のような「不要オブジェクト」を解放しないことがあるようなのです。
そしてそのインスタンスが Flex プロファイラのメモリ使用量&インスタンス数に計上される、というのが悪夢。
Flex プロファイラは控えめに言っても動作が遅く、長期安定試験には向きません。(たまにスナップショット時刻が数時間前になり、オブジェクト数が解析不可能な状態になったり…) かといって数回の操作で計測すると、単調増加とは言えない増え方でインスタンス数が増えていき、メモリリークしているように見える、というオチ。
定期的に System.gc をして、直後にあるクラスインスタンスを new する… といったハック的なコードを書き加えながら、Flex プロファイラ上を数字を追いかけたところ、以下のような挙動をしていました。
結局、Flex プロファイラの情報は使わないことに。業務を十数回繰り返して IE の Private Bytes の推移が安定していることを確認して、折れ線グラフにしてメモリリークの心配は無い、ということにしました。
Flash Player & Flex 開発は、自分の肌に合わないということだけはよくわかりました。メモリ管理と GC の全容が明らかになってないというのが一番いただけない(僕がドキュメントを見つけられてないだけかも知れませんけど)。こういうの、たとえ原因が非公開部分にあっても、「あんたプロでしょ、なんでそんなことも知らないの」って言われて責任をかぶることになるので。
自分たちのビルド手順の問題で、パッチが当たっているはずの Flex のバグが治ってませんでした。というのが前回まで。Flex プロファイラで Flex モジュールのインスタンス数を追いかけても、ちゃんと解放されている様子。
でもって「何をもって、メモリリークが解消されたことの証明にするか」という議論になりました。SDK-18268 以外、自分達の書いたコードに解放漏れはありません、と断言できる資料が作れないとお客さんに説明出来ないよね、って話です。コミットチャージの推移? IE の Private Bytes の推移? Flex プロファイラが報告するメモリ使用量 or インスタンス数?
OS や IE のメモリ使用量はあまりあてにならないだろうと、Flex プロファイラの情報でやることに決まり、大測定大会が始まりました。
これが悪夢の始まり。
よくよく見ると、Flex プロファイラの情報が???だらけなんです。。
- 現在表示している画面の Flex モジュールが、ライブオブジェクト・スナップショットに出てこない。2回目に 1 インスタンスできた、と報告される・・・
- スナップショットのインスタンス数と、オブジェクト参照ビューに出てくるオブジェクト数が一致しない・・・。
そしてとどめが
「被参照数が 0 のインスタンスが残ってる、しかも大量」
というもの。
どうやら Flash Player は、いくら GC を動かしても、以下のような「不要オブジェクト」を解放しないことがあるようなのです。
- Mark & Sweep でマークされなくなったオブジェクト
- 被参照数が 0 になったオブジェクト
そしてそのインスタンスが Flex プロファイラのメモリ使用量&インスタンス数に計上される、というのが悪夢。
Flex プロファイラは控えめに言っても動作が遅く、長期安定試験には向きません。(たまにスナップショット時刻が数時間前になり、オブジェクト数が解析不可能な状態になったり…) かといって数回の操作で計測すると、単調増加とは言えない増え方でインスタンス数が増えていき、メモリリークしているように見える、というオチ。
定期的に System.gc をして、直後にあるクラスインスタンスを new する… といったハック的なコードを書き加えながら、Flex プロファイラ上を数字を追いかけたところ、以下のような挙動をしていました。
- シングルトンなどの長寿命なインスタンスと同時期に new したインスタンスは、解放されないみたい。(長寿命インスタンスとメモリブロックを共有した様子。メモリブロックの共有については Flex ヘルプに書いてあります)
- 不要オブジェクトは System.gc() のときに解放されるものと、new のときに解放されるものとがあるみたい。
- new のときに解放されるのは new しようとしているクラスの不要オブジェクトだけみたい。
- 解放されない不要オブジェクトの個数は、該当クラスの new の回数と相関性があるみたい。(6 回目の new で 1 個残る、とか)
結局、Flex プロファイラの情報は使わないことに。業務を十数回繰り返して IE の Private Bytes の推移が安定していることを確認して、折れ線グラフにしてメモリリークの心配は無い、ということにしました。
Flash Player & Flex 開発は、自分の肌に合わないということだけはよくわかりました。メモリ管理と GC の全容が明らかになってないというのが一番いただけない(僕がドキュメントを見つけられてないだけかも知れませんけど)。こういうの、たとえ原因が非公開部分にあっても、「あんたプロでしょ、なんでそんなことも知らないの」って言われて責任をかぶることになるので。


How to use Quote function: