21

我们有一个 ASP.NET 应用程序,围绕 MonoRail 和 NHibernate 构建,我注意到在 64 位模式或 32 位模式下运行它时会出现奇怪的行为。一切都编译为 AnyCPU,并且在两种模式下都可以正常运行,但内存使用情况差异很大。

查看 ANTS 的以下快照:

32bit_snapshot:在此处输入图像描述

对比

64位快照:在此处输入图像描述

两个快照的使用场景非常相似(我在两次运行中都点击了相同的页面)。

首先,为什么在 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 字节边界对齐。堆栈中的两个参数占用与三个相同的内存量(返回地址占用缺少的 8 个字节)。Gnu malloc 将分配的区域对齐到 16 字节边界。

如果分配单元的大小很小,那么开销就会很大:首先是对齐数据的开销,然后是对齐与数据关联的簿记的开销。

我还预测,在 64 位系统中,数据结构已经发展:平衡的、splay 或任何树可能有意义,而不是二进制或 2-3-4但可以使用保证存在的 SSE 扩展来快速处理。

于 2012-11-06T16:49:22.417 回答
2

我不能确切地告诉你发生了什么,但可能会做一个很好的猜测。32 位进程的内存限制与 64 位进程不同。CLR 会经常在 32 位进程中运行 GC。您可以通过图表上的尖峰看到这一点。但是,当您运行 64 位进程时,在内存不足之前不会调用 GC。这将取决于您系统的总内存使用情况。

在数字上,您的 32 位进程只能分配大约 1gig,而您的 64 位进程可以分配所有内存。在 32 位进程中,GC 将更快开始清理,因为您的程序在使用过多内存时会降低性能。当您的总系统内存降至某个垃圾保留以下时,64 位进程上的 CLR 将开始清理。

于 2012-11-05T09:45:27.117 回答