ゲーム開発進捗 2016/02/12 またまたGCとパフォーマンス

どういった場合に GC の対象となるか調べてコードをいくつか改善してみました。おおざっぱなキャプチャしかとってなかったのであんまり参考にならないですが、改善前はこんな感じ。

2016-02-07 11_11_05-CpuGameDanke1UAP - Microsoft Visual Studio

10秒の間に2~4回ぐらい GC が発生していました。

改善した結果がこちら。

2016-02-11 20_12_39-CpuGameDanke1UAP - Microsoft Visual Studio - コピー

10秒に1~2回ぐらいまで抑えられました。まだ改善できそうな箇所があるのでもう少し頑張ってみます。

まあ GC の発生を改善すれば処理速度向上するかなーと思ってたんですが、気持ち程度でしたね。ただ、確実によくはなっていると思います。

とりあえず現状のパフォーマンスでユニットをたくさん出してみました。

2016-02-11 23_57_23-CpuGameDanke1UAP.Windows - コピー

ユニットがどれだけいるかわからないのですが、一応開発マシンでは FPS が 50~60 でている感じです。ただ、開発マシンはスペックが高く、ノートでやると明らかに落ちているのでまだまだ改善しないといけないですね。というかそもそもこんなにユニット出すのかっていう前提もあるんですが (^^;)

ロジックを最適化する場合、たいていは無駄な判定とか減らすのですが、それをやると正常に動かなくなることが割と多いです。これを直すのに意外と時間かかったりしますね。

]]>

ゲーム開発進捗 2016/02/07 GC とパフォーマンス

来週艦これのイベントが始まるということで、イベントが始まる前にマンスリー任務やEOステージのクリアをやってたのでゲーム開発のほうはあまりはかどりませんでした。それよりもどんどんたまっていくアニメの録画の消化をどうにかしたい…。

さてゲーム開発のほうですが、現在は Ver 0.20 の公開に向けて作っています。ですが、ちょっとパフォーマンスに難ありな状態なので、機能の作りはおいておいてメモリ管理のほうを少しやってました。

Visual Studio 2015 には診断ツールがあり、メモリの使用状況や CG の発生タイミング、メモリのスナップショットなどを見ることができます。

2016-02-07 11_11_05-CpuGameDanke1UAP - Microsoft Visual Studio

ゲームの場合ツール系とは違い、常に処理が回っているのでメモリ(インスタンス)の確保が常に発生します。C言語のような完全なネイティブプログラムの場合、自身でメモリの破棄タイミングを指定しなければならないので、メモリリークさえ気を付ければ GC なんて考えなくてもいいのですが、今回 C# でゲームを作っており、確保したメモリの破棄はほぼすべて GC に任せることになります。

ゲームループ中に GC の発生を抑えることはほぼ不可能です。事前に必要なメモリを確保しておき、その中でやりくりするという方法がゲームでは主流ですが、マネージドなプログラムだと、文字列処理を行うだけで GC 対象になるので相当気を使います。

とは言ってもあまり余計なインスタンスを作成さえしなければ、GC が発生してもゲームに影響することはそんなにありません。上の図で何回か GC が発生していますが、メモリが平行に進んでいる部分のGCは大体ジェネレーション1のものです。1回当たりにかかる時間はミリ秒単位。うまく作ってればコンマミリ秒まで落とせるので支障はあまりないと思います。

ただ、別のシーンに切り替えたときなどに例えば大きな規模の初期化処理などを行うとジェネレーション2が使用されます。これを放置しておくとゲームの最中で突然一気に解放されたりします。これにかかる時間が100ミリ秒単位だったりするので、その間完全にゲームが停止します。リアルタイム性が求められるゲームの場合致命的です。上の図でも途中で一気にメモリが解放されていることが分かります。

変なタイミングで発生されても困るので、初期化処理が終わったらとっとと GC.Collect を呼んで解放してしまうのがいいと思います。

2016-02-07 22_38_37-CpuGameDanke1UAP - Microsoft Visual Studio

プレイヤーが操作中に止まるよりは、次のシーンが始まる前の真っ暗な画面なんかで実行したほうがいいですね。操作中に0.5秒止まるよりは真っ暗な画面で0.5秒止まってたほうが、ユーザーは全然気にならないと思います。

]]>