6

私は2Dプラットフォーマーゲームを作成しており、レベルを表すために、位置、タイプ、およびさまざまなフラグのフィールドを持つクラスであるタイルの2D配列を使用しています。classタイル クラスのキーワードを に変更するstructと、読み込まれたマップのメモリ消費量が約 20% 減少します。

この動作の是非はわかりませんが、メモリ消費量の違いの理由を知りたいだけです。

編集: 数値はクラスとしてタイルを含む 1038 MB、構造体として 845 MB (ほとんどのゲーム データなし) です。

4

3 に答える 3

11

オブジェクトの配列は実際には参照の配列であり、オブジェクトはヒープに格納されます。

つまり、参照には 4 または 8 バイト (x86 または x64 に応じて) のオーバーヘッドがあり、ヒープ上の各オブジェクトには 8 または 16 バイトのオーバーヘッドがあります。

構造体の配列では、構造体の値が配列に直接格納されるため、余分なオーバーヘッドはありません。

たとえば、データが 48 バイトの場合、余分な 12 バイト (x86 モード) は、使用されるメモリの合計の 20% のオーバーヘッドになります。

使い方にも違いがありますので注意してください。タイルを移動したり、パラメーターとしてメソッドに送信したりすると、構造体を使用するとすべてのデータがコピーされますが、クラスを使用すると参照のみがコピーされます。構造体を 16 バイト未満に抑えることができれば、パフォーマンスの差は小さくなりますが、大きい場合は、クラスを使用してコードを高速化できます。

于 2012-08-15T19:20:29.193 に答える
3

各オブジェクトには、型ハンドルへのポインターと syncblock インデックスを含む 8 バイトのヘッダーがありますが、構造体はインラインで割り当てられます。さらに、使用している参照型変数ごとにポインター サイズの参照を割り当てる必要があります。

この記事では、実行時にオブジェクトを作成して配置する方法について詳しく説明します。

于 2012-08-15T19:21:23.940 に答える
1

構造体型の格納場所 (変数、パラメーター、配列要素、またはフィールド) は、すべてのパブリック フィールドとプライベート フィールドの値を保持します。通常は連結されますが、パディングが含まれる場合もあります。クラス型の格納場所には、ヒープ オブジェクト (4 ~ 8 バイト) への (null の可能性がある) 参照が保持されます。ヒープ オブジェクトは、8 ~ 16 バイトのオーバーヘッドに加えて、オブジェクトとその先祖が保持するすべてのパブリック フィールド、保護フィールド、およびプライベート フィールドの内容を保持します。

保存するものが固定サイズの値のバンドルである場合は、ほとんどの場合、公開されたフィールドを持つ構造体を使用する必要があります。構造体は不変でなければならないという考えは、C# コンパイラが次のようなコードを使用していた時代にまでさかのぼります。

  読み取り専用 Point Pt = new Point(3,4);
  void Yippie() { Pt.X += 5; }

Yippie新しい一時的なインスタンスを作成し、それにPointコピーして、その一時的なインスタンスでプロパティ セッターをPt呼び出し、破棄します。Xこのようなナンセンスを防ぐ適切な方法は、コンパイラに「申し訳ありませんが、読み取り専用の構造体変数でプロパティ セッターを呼び出すことはできません」と言わせるのではなく、読み取り専用のプロパティを持つように構造を定義することだと誰かが考えました。セッターなし。行うべき適切なことは、変化しようとしている構造体のメソッドまたはプロパティがthisその宣言でそのように示すことを要求し、読み取り専用構造体でのそのようなメソッドまたはプロパティの使用を禁止することでした。

プロパティで構造体フィールドをラップするとパフォーマンスが低下するため、構造体の不変条件を強制する必要がある場合を除いて、これはお勧めしません。また、 structsreadonlyの宣言を避けることをお勧めします。宣言された構造体は、フィールドがアクセスされるたびに完全にコピーされるためです。

ちなみに、変更可能なクラスの型について注意すべき重要な点: 変更可能なクラス オブジェクトの状態には、そのフィールドの内容だけでなく、それに存在するすべての参照のセットも含まれます。場合によっては、これが役立つことがあります。多くの場合、重大な問題を回避する唯一の方法は、変更可能なオブジェクトへの参照を保持するエンティティがそのような参照を共有しないようにすることです。何かをクラス型にすると、参照が無差別に渡されるのを防ぐために余分な作業が必要になる場合、それは問題の型が構造体であるべきであるという良い兆候です。

于 2012-08-15T23:08:52.070 に答える