2

私のゲームはガベージを生成しすぎて、GC 時間が長くなるところまで来ています。私は周りを回って生成されたガベージを減らしてきましたが、大量のメモリを頻繁に割り当てている場所が1つあり、これを解決する方法に行き詰まっています.

私のゲームは、歩くと新しい領域が生成されるマインクラフト タイプの世界です。地形の頂点データを格納するために使用される新しい領域の作成時に割り当てられる、大きな可変サイズの配列があります。配列がデータで満たされた後、slimdx DataStream に渡され、レンダリングに使用できるようになります。

問題は、これが可変サイズの配列であり、GCHandle.Alloc を呼び出す slimdx に渡す必要があることです。可変サイズであるため、再利用するにはサイズを変更する必要がある場合があります。また、信じられないほど大量のメモリが必要になるため、各領域に最大サイズの配列を割り当てることもできません。Slimdx との GCHandle ビジネスのため、リストを使用できません。

これまでのところ、配列を大きくする必要がある場合にのみ配列のサイズを変更することは、私にとって唯一のもっともらしいオプションのようですが、うまくいかない可能性があり、実装するのが面倒になる可能性があります。配列の実際のサイズを個別に追跡し、アンセーフ コードを使用して配列へのポインターを取得し、それを slimdx に渡す必要があります。また、最終的に非常に大量のメモリを使用することになる可能性があるため、すべての配列のサイズを必要最小限に減らす必要があります。

私はこの解決策に飛びつくのをためらっています.誰かがこれに対するより良い解決策を見ているかどうか知りたいです.

4

3 に答える 3

1

SlimDX はオープン ソースであり、速度が遅すぎるため、パフォーマンス ニーズに合わせてオープン ソースを変更する必要があります。ここで私が見ているのは、はるかに大きな配列を保持したいが、実際に使用されている領域のみを SlimDX に渡して、この潜在的に巨大な配列への追加のメモリ割り当てを防ぐことです。

.NET Framework には、まさにこの目的のために作成されたArraySegmentという名前の型があります。

// Taken from MSDN
// Create and initialize a new string array.
String[] myArr = { "The", "quick", "brown", "fox", "jumps", "over", "the", 
                   "lazy", "dog" };

// Define an array segment that contains the middle five values of the array.
ArraySegment<String> myArrSegMid = new ArraySegment<String>( myArr, 2, 5 );


public static void PrintIndexAndValues( ArraySegment<String> arrSeg )  
{
   for ( int i = arrSeg.Offset; i < (arrSeg.Offset + arrSeg.Count); i++ )  
   {
        Console.WriteLine( "   [{0}] : {1}", i, arrSeg.Array[i] );
   }
   Console.WriteLine();
}

つまり、通常の配列ではなく動作するオフセットとインデックスを常に使用する必要があるため、ArraySegment の使用法がやや奇妙であることがわかりました。代わりに、はるかに使いやすいゼロベースのインデックス作成を可能にする独自の構造体を抽出できますが、インデックスベースのアクセスごとにコストがかかり、ベースオフセットが追加されます。しかし、使用パターンが主に foreach である場合は、それほど重要ではありません。

毎回構造体を割り当て、スタック上の値ですべてのメソッドに渡すため、ArraySegment もコストがかかりすぎる状況がありました。その使用が問題ない場所と、高すぎるレートで割り当てられていないかどうかを注意深く監視する必要があります。

于 2012-07-08T05:45:18.417 に答える
1

Slimdx ライブラリとのより緊密な統合をお勧めします。これはオープン ソースであるため、レンダリングに必要なクリティカル パスを掘り下げて見つけることができます。次に、DMA スタイルのメモリ共有アプローチを使用して、より緊密に統合できます。

于 2012-07-06T22:54:54.507 に答える
0

.NETに準拠していない可能性のある古いライブラリslimdxの問題に同情します。私はそのような状況に対処しました。

提案:

  1. よりパフォーマンス効率の高いジェネリックリストまたはArrayListのような配列を使用します。配列のサイズを追跡するので、追跡する必要はありません。リストを一度にチャンクで割り当てます。たとえば、一度に100個の要素を割り当てます。
  2. C ++ .NETを使用して、安全でない配列またはArrayListなどの.NETクラスを利用します。
  3. 更新:仮想メモリのアイデアを使用します。一部のデータをXMLファイルまたはSQLデータベースに保存して、大量のメモリを解放します。

どちらにしてもギャンブルだと思います。

于 2012-07-07T00:46:39.130 に答える