21

MonoRail と NHibernate を中心に構築された ASP.NET アプリケーションがあり、64 ビット モードまたは 32 ビット モードで実行する場合に奇妙な動作に気付きました。すべてが AnyCPU としてコンパイルされ、両方のモードで正常に動作しますが、メモリ使用量は劇的に異なります。

ANTS からの次のスナップショットを見てください。

32bit_snapshot:ここに画像の説明を入力

64bit_snapshot:ここに画像の説明を入力

両方のスナップショットの使用シナリオはほとんど同じです (両方の実行で同じページにヒットしました)。

まず、64 ビット モードで未使用メモリが非常に多いのはなぜですか? また、64 ビット モードでアンマネージ メモリのサイズが 4 倍になるのはなぜですか?

これに関する洞察は本当に役に立ちます。

4

3 に答える 3

15

64 ビット プロセスの初期メモリ割り当ては、同等の 32 ビット プロセスの場合よりもはるかに多くなります。

理論的には、これによりガベージ コレクションの実行頻度が大幅に低下し、パフォーマンスが向上します。また、一度に大きなメモリ ブロックが割り当てられるため、断片化にも役立ちます。

この記事: http://blogs.msdn.com/b/maoni/archive/2007/05/15/64-bit-vs-32-bit.aspxで、より詳細な説明が得られます。

アンマネージ メモリの使用量が多いのは、おそらく、32 ビット モードで実行されている .NET オブジェクトが最低 12 バイト (8 バイト + 4 バイトの参照) を使用するのに対し、64 ビット モードの同じオブジェクトは 24 バイト (12 バイト) を使用するためです。バイト + 8 バイト参照)。

これをより完全に説明する別の記事: http://www.simple-talk.com/dotnet/.net-framework/object-overhead-the-hidden-.net-memory--allocation-cost/

于 2012-11-06T00:38:01.593 に答える
3

64 ビット システムでのメモリの問題に対する標準的な回答は、ほとんどのメモリ操作がデフォルトで 16 バイトにアラインされているというものです。128 ビット XXM レジスタとの間のメモリ読み取りは、16 バイト境界に整列することが期待されます。スタック内の 2 つのパラメーターは、3 つのパラメーターと同じ量のメモリを使用します (戻りアドレスは不足している 8 バイトを使用します)。Gnu malloc は、割り当てられた領域を 16 バイト境界に揃えます。

割り当てられたユニットのサイズが小さい場合、オーバーヘッドは非常に大きくなります。最初にデータの整列によるオーバーヘッドが発生し、次にデータに関連付けられた簿記の整列によるオーバーヘッドが発生します。

また、64 ビット システムではデータ構造が進化したと予測します。バイナリ、または 2-3-4 のバランスのとれた、スプレイなどのツリーの代わりに、多くのスラックを持つ可能性のある基数 16 のツリーを持つことが理にかなっている可能性があります。しかし、そこにあることが保証されている SSE 拡張で高速に処理できます。

于 2012-11-06T16:49:22.417 に答える
2

何が起こっているのか正確には言えませんが、おそらくうまく推測できます。32 ビット プロセスには、64 ビット プロセスとは異なるメモリ制限があります。CLR は、GC を 32 ビット プロセスで頻繁に実行します。これは、グラフのスパイクで確認できます。ただし、64 ビット プロセスを実行している場合、メモリが少なくなるまで GC は呼び出されません。これは、システムの総メモリ使用量によって異なります。

数字では、32ビットプロセスは約1ギガしか割り当てることができず、64ビットプロセスはすべてのメモリを割り当てることができます. 32 ビット プロセスでは、プログラムが多くのメモリを使用するとパフォーマンスが低下するため、GC はより早くクリーンアップを開始します。64 ビット プロセスの CLR は、システム メモリの合計が特定のごみ箱を下回ると、クリーンアップを開始します。

于 2012-11-05T09:45:27.117 に答える