新人PGとの書簡 メモリリーク事例1

「.Netで開発したデスクトップアプリ製品が、半日くらい使用するとだんだん遅くなってフリーズしまう」という事で相談を受けた事があります。
コードをgrepすると、それだけで2千カ所のメモリーリークを起こすであろうコードが見つかりました。実効ステップ数10万行ほどのシステムです。
さらに動的にメモリ内の状態を分析すると、メモリを握ったままのシステムリソース(.Netなのでアンマネージドリソースですね)が大量にWindows OSのメモリ空間に存在し、そのアンマネージドリソースを使ったオブジェクトの多くは、すでに参照が外れて消滅していました。典型的な.Net、Javaにありがちなメモリリークが大量に発生していたのです。

簡単に安全に修正できるパターンがほとんどでしたので、私は当時の開発元(日本を代表する大手SIer)に数千カ所を資料で示して修正してもらいました。その結果半日で落ちていたところを一日持つようにできました。その開発チームは、過去にリーダーが何人か変わったようでした(日本を代表する大手SIerでよく見られる運用)。

コードを分析すると、以前のリーダーがマイクロソフト推奨ののDispose Finalizerパターンを利用しようとして間違いを犯していたことがわかりました。結果的にこのようなメモリーリークを大量に産んでいたのです。私はFinalizerを実装している箇所を全て削除し、明示的に後処理でCloseなりDisposeなり呼び出すように指示しました。印刷時にメモリが枯渇、またオラクルのキャッシュメモリも枯渇という問題があり、使用メモリサイズが管理できていない事が問題の一部だったからです。開発元は関西が拠点でしたので、スカイプ越しにその理屈を説明するのが結構大変でしたが、最終的には修正を実施、結果を見て納得してもらいました。

次のステップとして、他に影響が出そうな箇所をパターン分けして、パターンごとの修正指示を出しました。簡単に治らないパターン、例えばアンマネージドリソースを握ったクラス内でそれを解放しておらず、あちこちでそのオブジェクトを使い回しているパターンなど、そういったコードが結構な数残っていました。いままでよりは問題は起きにくいレベルまでにはなりましたが、それらを一掃しないと確実にある割合のお客様のところで同様の問題が起きます。そして営業さんはずっと苦しい言い訳をしつづけなければなりません。
しかし、お客様は一日の最後にマシンをリブートする運用が可能という理由で、その修正を後回しにして機能実装に人的リソースを振り分ける選択をしてしまいました。瑕疵担保期間内で実施していたのですが、なにか政治的な判断もあったようです。

いまはそのようなバグも修正されているはずですが、本来、数年稼働し続けても動き続けるのが製品レベルのアプリです。しかも現在ではクラウド上にウエブサービスで提供する形が普通ですので、上記のようなバグは一カ所も許されません。

Tさんは、先日説明した処理手順をまもって、メモリリークが起きないようにしてください。

Posted in

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

*

次のHTML タグと属性が使えます: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre class="">