web-dev-qa-db-ja.com

C#での「新規」のパフォーマンスコスト?

C#では、新しいキーワードを使用した場合のパフォーマンスコストはいくらですか?特にゲーム開発に関連して質問します。C++では、更新サイクルごとに新しいものを作成することは間違いなくノーノーです。同じことがC#にも当てはまりますか?私はXNAを使用しており、モバイル向けに開発しています。本当に最適化の質問として尋ねるだけです。

33
tweetypi

newのコストには3つの部分があります。

  • メモリの割り当て(値型の場合は必要ない場合があります)
  • コンストラクターの実行(実行している内容によって異なります)
  • ガベージコレクションのコスト(これも、コンテキストによっては、値型の場合は適用されない場合があります)

メインコードにany新しいオブジェクトを作成せずにC#を慣用的に使用することは困難です...オブジェクトを可能な限り再利用することで実現可能だと思いますが。実際のデバイスをいくつか手に入れて、ゲームのパフォーマンスを確認してください。

このようなマイクロ最適化は通常プログラミングでは避けるべきですが、他の場所よりもゲームループに適している可能性が高いことは確かです-明らかにゲームは小さな一時停止にも非常に敏感です。ただし、GCのコストが原因で時間の経過とともに分散するため、より多くのオブジェクトを使用するコストを判断するのは非常に難しい場合があります。

アロケーターとガベージコレクターは.NETでかなり優れていますが、デバイス(Windows Phone 7だと思います)ではもっと簡単になる可能性がありますか?特に、Compact Framework CLR(WP7が使用するもの)に世代別GCがあるかどうかはわかりません。

35
Jon Skeet

C#での割り当ては、実際にはC++よりも高速です。ヒープポインタを増やしてそのポインタを返すだけです。一般に、オブジェクトはC++よりもC#の方がnewedを頻繁に取得します。これは、 strings などに関係する不変性が少し多いためです。

他の人が指摘しているように、本当の獣はガベージコレクターであり、プロファイルを作成するのは少し難しいです。それにもかかわらず、GCでさえ、ほとんどの場合、C++のdeleteと同じくらい高速ですが、いつ発生するかを予測することはできません。

.NETチームのパフォーマンス担当者であるRicoMarianiによるヒント: http://msdn.Microsoft.com/en-us/library/ms973837.aspx

それは少し古く、GCにいくつかの改善がありましたが、ほとんどの情報は依然として関連しています。

ただし、XNA/Compact Frameworkのガベージコレクターは、CPUとメモリのパフォーマンスをトレードオフするために、x86バージョンよりも多少遅いので注意する必要があります。

[〜#〜]編集[〜#〜]

言及するのを忘れました、そしてこれは重要です: 値型 構造体を含めて、new構文も使用しますが、それらはヒープではなくスタックに作成されるので、 box それらを除いて、それらのGCコストはありません。

19
Rei Miyasaka

新しいオペレーター自体のコストはごくわずかです。コストがかかる可能性があるのは、カスタムコンストラクターで発生する処理です。したがって、このコンストラクターで多くのことが行われている場合は、問題になる可能性があります。

6
Darin Dimitrov

常に「最も簡単な」方法をコーディングする必要があります次にボトルネックを測定しますifそれらは存在します。

とにかく、私はC#でゲームをコーディングすることはありません。

[〜#〜]編集[〜#〜]

それは憤慨を引き起こしたので、私はC#でコーディングしたことがないことを意味しますif C++は利用可能なオプションでした。 OPもC++にタグを付けているので、これは私が思ったことです。

5
Simone

new自体のコストはおそらく重要ではありませんが、ヒープに新しいオブジェクトを割り当てると(参照型のインスタンスを作成するときに)ガベージコレクションがトリガーされる可能性があるため、ゲームでは副作用が重要になる可能性があります。 GCが心配な場合は、値型を使用するか、オブジェクトを再利用できます。

また、Darinが正しく指摘しているように、コンストラクターは多くの作業を行う可能性があります。

3
Brian Rasmussen

C#のnew演算子に関連するコストはほとんどありませんが、参照型でnewを使用すると、ヒープ割り当てがそこにあり、これはGCによって維持されます。メモリが連続している場合、メモリの割り当ては単なるポインタの移動ですが、2つの割り当て間のギャップが見つかった場合、GCは使用可能なメモリの空きリスト(リンクリスト)を参照して必要なオブジェクトを見つけます。これには時間がかかる場合がありますo(n)旅行時間。

Eric Lippertによる投稿を参照

2
TalentTuner

C#でnewを書き込むと、CLRはマネージヒープ上のオブジェクトにメモリを割り当てます。

詳細については、以下のリンクをご覧ください。

http://msdn.Microsoft.com/en-us/library/ee787088(v = vs.100).aspx

ガベージコレクションはC#では自動であるため(テスト中にGC.Collectを使用して手動でトリガーする場合のみ)、c#でのゲームデザインは不適切です考え。

デストラクタがあるので、目的のためにC++を探す必要があります。

~ClassName()
{
//kill my object and reclaim memory.
}
1
Sid

C#では、メモリはガベージコレクタによって最適化されたままであるため、メモリの検索と割り当ては非常に高速な操作です。ただし、GCによって実行されるときどきの最適化は、大幅に遅くなる可能性があります

1
Armen Tsirunyan

私の測定によると、参照型の「新しい」には2.2秒かかることもあれば、数ティックの速さになることもあります。結論として、.net GCにはリアルタイムの保証がなく、パフォーマンスはランダムに大幅に変化する可能性があります。したがって、リアルタイムのデザインをお勧めします。ゲームでは、コードのリアルタイム部分(更新ループなど)の型を参照するために「新規」と呼ばないでください。リアルタイムの保証はありません。

もちろん、多くの人は、「新しい」の所要時間は2.2秒であり、数時間に1回だけ発生する場合は問題になると主張します。さて、これは設計者の判断でなければなりません。しかし、学術的な議論のために、GCはリアルタイムではないため、リアルタイムコードで「新規」とは呼ばないでください。

0
Nick