はかせのラボ

私の頭の中を書いていく雑記ブログです

DirectX STLコンテナは内部的にオブジェクト作ってるっぽい

あいさつ

どうも、はかせです。
今回はメモリ増加バグに遭遇しその解決のため悪戦苦闘した話です。

どういうバグ?

プレイすればするほどメモリが増加していくというバグです。
ただ毎プレイではなく何回、何十回とやって1MBずつ増えていくという感じです。
つまり毎プレイ数KBずつ増えていき単位がMBになった時にプロファイラーで気づくという感じですね。
(なのでおそらく今回が初ではなく今までもあったが気づいていなかっただけという感じだと思われます)

なぜそれに気づいたかというと単純に負荷テストで100回ぐらい回したからです。
以下プロファイラーの画像(わかりやすく変化している最初のほう)
f:id:hakase0274:20190129224600p:plain

18、19回目で急激に増えていますが、
これはプレイ初期でオブジェクトプールに不足分を足しているため
予定通りの結果です。

100KBぐらいは各種更新処理の時のローカル変数確保があるので
誤差かなと思いますが、それが毎プレイ発生しているのが問題です。

VisualStudioのプロファイラー機能は前回取ったスナップショットとの差分を取ります。
つまり前回から増えているということになります。
(ただManagedヒープの中身しか詳細は見れていないのでスタックなどに積まれている分も含めると割と順当なのかもしれません)

原因は?

こいつらです。
f:id:hakase0274:20190129230017p:plain
f:id:hakase0274:20190129230112p:plain

Collider2Dというのは2Dコライダーのベースクラスです。
このクラスを継承したコライダークラスをアタッチすることで衝突が可能になります。

こいつらのオブジェクトがプレイするたびに増えているのがメモリ増加の原因のようです。
ただ私はベースクラスを生成してはいません。
ではなぜ生成されているんでしょう?

解決

答えはSTLコンテナでした。
こいつらは内部的にテンプレートで渡された型を生成しているようです。
(まぁそうしなきゃ使えないよね)

私は衝突判定時に存在しているコライダーをSTLコンテナに格納して
管理しています。

その時に配列のキャパシティ(要は確保メモリ)が不足していれば
追加で確保するわけですがその時に作られていたようです。

なので確保する理論値が取れたらそれ以降は増えません。
(最初の画像の26回目がそれです)

その他の100KB程度の増加はスナップショットを
取ったタイミングで変わっていたので
ローカル変数の解放がされているかいないかとかそういうOSや言語サイドの
メモリ管理の問題っぽいです。

あとがき

今回は負荷テストの中でメモリがわずかに増加し続ける問題でした。
結果としてはバグでもなんでもなくただの仕様通りの動きでした。

今回学んだこととしてちゃんと標準ライブラリの中身見てからバグかどうか判断しようということです。
ただの仕様通りの動きをしていただけなのにバグだと思い
今日1日をつぶしてしまいましたorz

まぁ失敗した経験を得たことはきっと無駄ではないはず・・・
(最近ずっと空回り気味だなぁ)

それでは今回はこの辺でノシ