02. メモリリークの検出(C++)

C++版にはLive2Dの内部で確保したメモリに関して、リークしているかどうかを検出する機能があります。
具体的にはinit()からdispose()までにLive2Dが確保したメモリについての情報をダンプします。

※ この機能はDEBUGビルド時しか機能しません。 ( VisualStudioなら_DEBUG、XCodeならDEBUGマクロが有効の時)

//initを呼ぶ前にフラグを設定します。
UtDebug::addMemoryDebugFlags( UtDebug::MEMORY_DEBUG_MEMORY_INFO_COUNT ) ;

Live2D::init(  );

/***** モデルやモーションの生成、破棄 *****/

Live2D::dispose();//この時にメモリ情報を表示します。

出力例
----------------- Live2D Memory Info -----------------
Successfully cleaned (no memory leaks found). 

  local malloc count  : remaining     : 0
  local malloc count  : total         : 48884
  local malloc memory : current       : 0 byte
  local malloc memory : peak          : 539 KB
  local malloc memory : total         : 1351 KB

  allocator malloc count  : remaining : 0
  allocator malloc count  : total     : 109
  allocator malloc memory : current   : 0 byte
  allocator malloc memory : peak      : 604 KB
  allocator malloc memory : total     : 802 KB

  LDObject           instance count : 1
  LDObject           total count    : 47303
  LDUnmanagedObject  instance count : 0
  LDUnmanagedObject  total count    : 1
------------------------------------------------------

出力のうち重要なのは
local malloc count : remaining

allocator malloc count : remaining
の項目です。
これらが0になっていない場合はLive2D関連のオブジェクトの解放忘れがあります。



    Live2Dのメモリ構造について
Live2D SDKの仕様として、モデルやモーション間でID情報は共有する構造になっています。
新しいモデル(またはモーション)を読み込んだ際、これまで1度も使われていないIDの場合は新たにIDを保持します。
モデル(モーション)を破棄した後も元のサイズには戻らずリークした印象となります。
同じモデルをロード・削除する度にメモリ使用量が増える場合はメモリリークと思われますが、初回ロード時しかメモリが増えない場合それは正常な動作となります。

また、事前にモデル・モーションでのIDの使用数が推測しにくく、ダウンロードによる新規モデル追加などのケースも有り得るため
現状では大きめに確保するよりは、必要に応じて確保する方式を採っています。

Live2D内部のメモリ管理では、共通領域、各モデル、各モーション、それぞれに異なる領域にまとめてデータを確保・破棄していく事で断片化が発生しにくい仕組みになっています。
modelAとmodelBの2つがいた場合、modelAのメモリ領域は、modelB のメモリ領域と完全に分離されています。
modelAを破棄した際は、modelAに使われていたメモリ領域が完全に再利用可能になります。

modelA 1つが利用するメモリ領域も単一の連続領域で確保するのではなく、複数のページ(最低4KBのまとまったメモリ領域)で構成されております。
各ページから実際のポインタサイズに応じて分割利用します。

より大きなメモリを使用するmodelCを後からロードする場合も、より小さなmodelAのメモリ領域を再利用しつつ、足りない分だけページを確保してロード可能となります。


Comments