かたちづくり

つれづれに、だらだらと、おきらくに

Hisui でメモリリーク?

弊社の OpenGL フレームワーク Hisui について、OutOfMemoryExcepion が発生するという報告を頂いています。

C#特有の?、、、というか初心者の私には理解できない現象に悩む。
PCが重くなって固まってゆく、、、
最終的にはOutOfMemoryExceptionでさようなら、、、

ヒスイ( C# OpenGL Framework) でNCシミュレータ (2) - てきとうな日々 - Yahoo!ブログ

obj形式ファイルを読み込んで、前のデータは削除する。
を繰り返すとメモリーをどんどん食いつぶして動作不能になります。objファイルのサイズはせいぜい10M程度です。

Hisui Support Board

検証のため下記のコードを書いてみましたが、メモリ使用量は一定量に抑えられており食い潰されることはありませんでした。
(会社の製品に対するサポートを個人のブログでやっていいものかどうかと思いつつも、こちらの方が書きやすいという理由でこの場で検証結果を報告します)

      static readonly Timer _timer = new Timer { Interval = 100 };

      [Hisui.Ctrl.Command]
      static void RepeatFileLoading()
      {
        // 読み込む OBJ ファイルの配列を作る
        var files = Directory.GetFiles( @"d:\data", "*.obj" );
        int index = 0;

        // 読み込んだ OBJ の登録先エントリ。null で初期化しておく。
        Core.IEntry entry = null;

        // 【重要】ヒストリを無効にし、Undo/Redo用バッファでメモリが食いつぶされることを防ぐ。
        SI.History.Enabled = false;

        // タイマーイベントでデータを読み込む
        _timer.Tick += ( sender, e ) =>
          {
            // 前のエントリを削除
            if ( entry != null ) SI.RemoveEntry( entry );

            // ファイルを読み込みエントリに登録
            entry = SI.PutEntry( Spatial.Formats.ObjFormat.Import( files[index] ).First() );

            // index を1つ進める
            index = (index + 1) % files.Length;

            // 更新処理。描画用のデータが構築される。
            SI.Build();
            
            // ガベージコレクション。
            GC.Collect();
            GC.WaitForPendingFinalizers();
            GC.Collect();

            // ビューのフィット処理。
            SI.View.Fit();
          };

        // タイマーをスタート
        _timer.Start();
      }

つまり私としては「ヒスイには問題はないのではないか」と思っているのですが、とはいえ catfalcon 様(質問者)にご提示頂いたコードにも特に問題があるようには思えず、どうしてだろうと首を傾げているところです。

C# や Java のようなガベコレがある言語でのメモリリークは、経験上イベントハンドラに原因があることが多いと思います。思わぬところに参照が残っていると、不要なオブジェクトなのにガベコレが回収してくれないということが起こりえます。経験では特にイベントハンドラ周辺でこの見落としをすることが多く(私は何度もハマった・・・)、不要になったオブジェクトからはイベントハンドラをきっちりデタッチしておくことが肝要なようです。

しかし catfalcon 様のブログを拝見する限りかなりの力量をお持ちの方と推察しておりますので、このようなことは釈迦に説法かもしれません。何か新しいことが分かりましたらご報告頂ければと思います。

申し訳ありませんが本年のサポートは本日を持って終了とさせて頂きたいと思います。それでは良いお年を。来年もよろしくお願い致します。