32位池和64位池之间的内存使用情况

21
我们有一个ASP.NET应用程序,基于MonoRail和NHibernate构建,我注意到在使用64位模式或32位模式运行时存在奇怪的行为。所有内容都编译为AnyCPU,在两种模式下都可以正常运行,但内存使用情况有很大区别。
请看ANTS的以下截图:
32-bit快照: enter image description here 对比
64-bit快照: enter image description here 两个快照的使用场景几乎相同(我在两次运行中都访问了同样的页面)。
首先,为什么64位模式下未使用的内存如此之高?为什么64位模式下未管理的内存是32位模式下的四倍?
如果有任何见解,将非常有帮助。
3个回答

15

64位进程的初始内存分配比等效的32位进程高得多。

理论上,这使得垃圾回收运行的次数要少得多,应该可以提高性能。它还有助于防止内存碎片,因为每次分配较大的内存块。

这篇文章: https://devblogs.microsoft.com/dotnet/64-bit-vs-32-bit/ 给出了更详细的解释。

你所看到的更高的非托管内存使用可能是由于在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/


谢谢你的文章,解释得非常清楚。然而,我仍然看不到非托管内存部分的相关性,这部分内存仍然是由非托管代码分配的,而不是CLR本身,对吗? - jishi
我会相信如果差异小于100%,但它是300%:/ 其他原因必须是导致这种情况的原因。 - jishi
如果对象不为空,并且每个对象包含多个属性,这些属性分配的数据比它们的32位版本更多,那么这可能会解释这个问题。但是,如果没有深入了解内存配置文件的详细信息,无法确定。 - CIGuy
@jishi,你知道你的未托管代码发生了什么吗?也许它只是有内存泄漏?此外,我认为可能会为未托管代码分配大量保留内存,就像你的托管应用程序一样。 - Shelest
不,我对此没有任何见解。我们自己没有未管理的代码,所以这是来自依赖库。我们没有看到这些库中有任何内存泄漏的迹象,我的主要猜测是内存用于NHibernate和/或GDI(我们进行了大量的图像调整)。 - jishi
显示剩余3条评论

3
64位系统解决内存问题的标准答案是,默认情况下,大多数内存操作都会对齐到16字节。预期128位XXM寄存器的内存读写要与16字节边界对齐。栈中的两个参数所占用的内存与三个参数相同(返回地址占用缺失的8个字节)。Gnu malloc将分配区域对齐到16字节边界。
如果分配单元的大小很小,则开销将非常巨大:首先是由于数据对齐而产生的开销,然后是与数据相关的簿记对齐的开销。
此外,我预测在64位系统中,数据结构已经发展:可能更有意义的是使用基数为16的树,而不是二进制、2-3-4、平衡、splay或任何其他树形结构,这种树可以有很多松弛但可以通过保证存在的SSE扩展快速处理。

我们应用程序中占用内存的大部分“数据”似乎是string[]对象。我确信更大的字符串不会有分配内存的困难,而且开销应该只是每个字符串末尾的几个字节。这几乎无法解释为什么内存利用率会是32位进程大小的数倍? - jishi
@jishi: 你能给出一个字符串长度的直方图吗?(我不是专家.NET实践,但我有丰富的想象力!) - Aki Suihkonen

2
我不能确切地告诉你发生了什么,但可能可以猜到。32位进程与64位进程具有不同的内存限制。CLR将在32位进程中频繁运行GC。您可以通过图表上的峰值看到这一点。然而,当您运行64位进程时,只有在内存不足时才会调用GC。这取决于您系统的总内存使用情况。
以数字表示,您的32位进程只能分配约1GB,而您的64位进程可以分配所有内存。在32位进程中,GC会更早地开始清理,因为当程序使用过多内存时,性能会受到影响。在64位进程中,CLR将在总系统内存降至某个阈值以下时开始清理。

听起来很合理,活动内存的差异并不是很大,可以解释为在64位运行时可能没有进行垃圾回收。但我好奇的是,为什么它会认为需要分配近1 GB的内存,当应用程序本身只使用约200 MB?而未经管理的内存,这并不能通过这种方式解释。 - jishi
你的机器上可能有几个G的可用空间。64位进程会获得一定量的可用内存。如果可用内存更少,进程将使用/获取更少的内存。尝试分配可用内存,64位进程将使用更少的内存。 - Peter

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接