定常時のガベージ発生を抑制するための各種調整

 XNA Game Studio 3.1で開発中のDragoon(仮)ですが、ガベージの発生については、対策が必要なほどではありません。

 しかし、どのようなコードでマネージドオブジェクトが生成されるのか、今回は特にXbox 360上での動作について、「XNA Framework Remote Performance Monitor」の統計を眺めながら、よく見直してみることにしました。
 ここでの基本方針は、明示的・暗示的に関わらず「ゲームの定常時(時間進行や描画の処理)でのマネージドオブジェクトの生成を抑え」、必要であれば「初期化時に済ませる」です。

 テスト用プロジェクトでステップ単位の実験をしたり、代替処理を作成したりしてみました。それらに基づいてゲーム本体を調整した結果、現状版の定常時(ラウンドの進行全般)でのボクシングの発生をなくすことができました。それでもある程度の量のマネージドオブジェクトの生成が常時起きているので、ゲーム本体コードでの全容をつかめているわけではありません。

 Dragoon(仮)では、ある程度考慮の元に作っていましたが、これまで以下のようなものが未対策と判明し、書き換えました。

  • EffectPassCollectionクラスのforeach文(先日の対策案)
  • StringBuilder.AppendFormatメソッド周辺で起こるToStringメソッド。「デバッグ用の動的テキスト生成」や「ゲーム画面表示用の動的テキスト生成」
  • 上記の場合も含めて、列挙型のToStringメソッド

 なお、定常時のガベージ発生の徹底排除が「必ずしもパフォーマンス向上につながる保証はない」ということも承知しておかなければなりません。対策によりオーバーヘッドの抑制になって、パフォーマンス向上になる部分もあれば、.NETが持つ処理をアプリケーションコードで置き換えることで遅くなってしまう部分もあるように思います。
 対策をしようとすると、「汎用性の低いコード」または「難解なコード」が増える場合もあります。リフレクションの有無にかかわる部分では、.NET Framework (Windows)では書けても、.NET Compact Framework (Xbox 360)では思いついた通りに書けないという部分もあります。

 「パフォーマンスが不自然に悪い」というならば「GCが動きすぎていないか調べてみよう」、そうでないならば「定常時にマネージドオブジェクトを量産しないように注意を払ったコードにしておこう」といったところでしょうか。