2012-03-17 20 views
6

私はC#、.NET 4.0、64ビットを使用しています。計算に使用される5億の「データポイント」をメモリに保存する必要があります。これらを構造体またはクラスオブジェクトとして作成するかどうかを決定する必要があります。 Structsはとても速く見えます。.NETスタックメモリ制限

スタックのメモリ制限はありますか?もしそうなら、どのように調整することができます。

スタックに大量のデータを格納すると、システムの全体的なパフォーマンスが影響を受けますか?

(ところで、私は.NETの単一オブジェクトサイズの制限を認識しているので、データは複数のコレクションに格納されます)。

+1

スタックをヒープと混同しないでください。 –

+1

あなたはどのような基準で構造体がクラスより "はるかに速い"と主張/仮定していますか? –

+0

私はOPがスタック割り当てと構造体の間に厳しい関係を作成すると推測しますが、これは間違っています。これらは完全に異なるテーマであり、*関連する*可能性があります。 – Tigran

答えて

6

あなたは間違った質問をしています。スタックサイズが重要な場合は、何か問題があります。

多くのデータポイントを使用する場合は、それらを配列などのコレクションに配置します。配列は常にヒープに割り当てられます。構造体の配列は個々の構造体を埋め込み、連続したメモリブロックを形成します。 (2GBを超える場合は、複数の配列が必要です)。

参照型では、配列には参照のみが含まれ、オブジェクトはヒープ上に個別に割り当てられます。ヒープ割り当てには約16バイトのオーバーヘッドがあり、配列内の参照は別の8を占めます。
また、迂回のためにキャッシュのローカリティが悪化し、GCがこれらの参照をクロールするために多くの作業を行う必要があります。

私の結論は、多くの小さなデータポイントがある場合、それらを構造体にして配列に配置することです。

1

データポイントのクラスを使用できます。この場合、メモリはヒープ上に割り当てられます。

しかし、あなたがアプリケーションのメモリ制限がより制限された.NETの世界でプログラミングしているため、特に5億データポイントについて考えると、sqliteなどの組み込みデータベースを使用することを強く推奨します。例えば。このようにして、すべてのデータポイントを同時にメモリに入れるのではなく、計算に必要なデータポイントをにするだけです。

+0

私の経験では、データベースのオーバーヘッドなしに大量のデータに高速アクセスすることが一般的です。また、それらをすべてメモリにロードすると、参照タイプを使用するためだけに12GBのオーバーヘッドが得られます。よくない。 – CodesInChaos

+0

@CodeInChaos:同意します。 Infactはそれらをすべてメモリにロードするのではなく、データを保持するためにいくつかの 'db'レイヤーを使います。 – Tigran

+1

パフォーマンス上の理由から、それらをすべてメモリに保持したいことがよくあります。たとえば、大規模な配列に数GBのデータが格納されている物理シミュレーションでよく働きます。 – CodesInChaos

4

データを配列に格納し、配列は常にヒープに格納されます。したがって、配列を保持するために構造体やクラスを使用するかどうかは関係ありません。データポイントの配列を連続したメモリブロックに効率的に割り当てることができるように、データポイントが値型(つまり構造体)であることを確認したいことがあります。

ヒープメモリとスタック割り当てメモリのパフォーマンスの違いは、短い時間内に割り当てられ、割り当てが解除された小さなオブジェクトで発生する可能性が高くなります。あなたが記述するサイズの長命オブジェクトの場合、スタックとヒープ割り当てメモリの間にパフォーマンスに違いはないと思います。

+0

事実は、構造体がヒープ上に割り当てられた場合、速い割り振りの「利点」(質問の観点から)が失われることです。 – Tigran

+0

@Tigranこれらの違いは、5億件のデータポイントで操作を実行すると測定不能になります。 –

+2

@Tigran配列の一部でない場合。構造体は配列内の連続したメモリブロックになりますが、クラスは新しいインスタンス(関連する16バイトのオーバーヘッド)と追加の迂回を取得します。 – CodesInChaos