.NET进程可以分配的最大内存

27
什么是.NET进程垃圾收集器可以分配的最大内存?当编译为x64时,Process.GetCurrentProcess.MaxWorkingSet返回约1.4GB,但当编译为AnyCPU(x64)时,返回相同的数字。对于x64,它应该更像“任务管理器”中显示的“限制”值。如何获取在所有情况下超过会导致OutOfMemory异常的正确数字?
一些方法应返回的示例: 1)机器配置:x64-Windows,4GB物理内存,4GB页面文件 -作为64位进程:8GB -作为32位进程:1.4GB
2)机器配置:x64-Windows,1GB物理内存,2GB页面文件 -作为64位进程:3GB -作为32位进程:1.4GB
3)机器配置:x32-Windows,4GB物理内存,4GB页面文件 -作为64位进程:不会发生 -作为32位进程:1.4GB
4)机器配置:x32-Windows,512MB物理内存,512MB页面文件 -作为64位进程:不会发生 -作为32位进程:1.0GB

这是一篇有趣的文章,讨论了.NET进程开始出现内存不足异常的理论最大值和范围:http://blogs.msdn.com/b/tom/archive/2008/04/10/chat-question-memory-limits-for-32-bit-and-64-bit-processes.aspx - Jeff B
2个回答

17

Windows可以配置为按需或根据请求分配更多页面文件空间。
作业对象可以防止消耗超过一定数量的内存。
堆的碎片化和其代际性质(以及需要将大型内容放入大对象堆)

所有这些意味着硬限制在实际中没有太多用处,并且回答“我可以理论上分配多少内存”的问题比你想象的要复杂得多。

由于这很复杂,任何一个人提出这个问题都可能试图做一些错误的事情,应该将他们的问题重定向到更有用的地方。

您试图做什么,看起来需要这样的问题呢?

"我只是想知道进程的当前内存负载何时可能会成为问题,以便我可以采取措施,例如释放自定义缓存中的某些项目。"

好的。这个问题更容易解决。

按复杂度顺序有两种解决方案:

  1. 让您的缓存使用弱引用
    • 这意味着系统几乎可以自动释放您的东西,但您对替换策略等方面的控制很少
    • 这取决于缓存数据比键和弱引用的开销大得多
  2. 注册垃圾回收通知
    • 这使您可以控制释放内容。
    • 您依赖系统具有适当的GC代最大大小,这可能需要一段时间才能达到稳定状态。

需要注意的事项。 维护这个庞大的缓存(听起来要去磁盘)真的比重新计算/重新请求数据更便宜吗? 如果您的缓存在常见/连续请求的项目之间表现出较差的局部性,则会花费大量精力进行数据分页。一个较小的缓存与有效调整的替换策略有很大机会表现得更好(并对其他正在运行的程序产生更少的影响)

另外:在.Net中,由于内存管理核心CLR结构的限制,没有变量大小的对象(字符串、数组)可以超过2GB。(上述任何一种解决方案都将从中受益)


我只想知道进程当前的内存负载何时可能会出现问题,以便我可以采取行动,例如释放自定义缓存中的某些项目。该值不需要100%准确,只需为我的缓存提供提示即可。我目前将可用物理内存量作为限制,但对于32位进程,这个限制更低。 - Rauhotz
顺便说一句:动态页面文件大小的观点很好,我错过了它,但现在我会满足于当前的限制。 - Rauhotz
嗯,那个问题是对这个问题的一种后续提问:https://dev59.com/x3NA5IYBdhLWcg3wgeOk。我正在打转。 - Rauhotz
好的,但你已经开始有所进展了。对我来说听起来你会从GC通知API中受益,如果没有第二代集合,那么你就没问题了。 - ShuggyCoUk

3
这不是取决于你有多少内存吗?
理论上,x64进程可以分配EB(艾字节)的内存,我想 - 也就是说,非常多。但是如果您这样做,您的计算机应该会开始疯狂分页并最终死机。
在32位模式下情况不同,因为您无法在Windows中任何进程中分配超过1GB的内存(是的,有方法可以解决,但不美观)。实际上,这意味着每个.NET进程大约7-800兆,因为.NET保留了一些空间。
无论如何,在32位中,您可以使用的最大内存为3GB - 操作系统为自己保留了1GB的虚拟空间。
在64位中,应该是2 ^ 64,这是一个很大的数字,但是http://en.wikipedia.org/wiki/X86-64说它是256TB的虚拟空间和1TB的真实内存。无论哪种方式,它都比您机器上可能拥有的要多得多,因此它将命中页面文件。
使用64位OS和64位运行时,基于.NET 2.0的应用程序现在可以利用500倍的内存来存储数据,例如服务器端缓存。
这里还有一些好信息http://www.theserverside.net/tt/articles/showarticle.tss?id=NET2BMNov64Bit
顺便说一句,如果您在x64机器上(即,x64机器+x64 OS),编译为AnyCPU和x64是相同的-它以x64模式运行。唯一的区别在于您是否使用AnyCPU与x86:
- x64 OS/.NET,AnyCpu:x64应用程序。 - x64 OS/.NET,x64:x64应用程序。 - x64 OS/.NET,x32:x32应用程序(x64 .NET框架作为Fx的x32和x64版本都安装了)。 - x32 OS/NET,AnyCPU:x32应用程序。 - x32 OS/.NET,x64:崩溃和燃烧宝贝!(实际上,它只是优雅地关闭)。 - x32 OS/.NET,x32:x32应用程序。

但是我如何获取计算机的实际内存限制? - Rauhotz
我将您的答案标记为不好,因为您混淆了一切。3GB内存是最大的可用物理内存,可以容纳一个或多个进程。任何进程都可以访问完整的4GB空间(32位寻址),不能在物理内存中的内存将被缓存(如果缓存设置正确)。而且3GB也不完全准确。您必须将XP设置为默认情况下应用程序最多只能使用2GB RAM,操作系统最多只能使用2GB RAM(物理内存)。 - Eric Ouellet
2
抱歉,Eric,但你需要仔细阅读并实际尝试一下。32位系统的理论极限可能是4GB,但Windows将您限制为3GB(另一个GB用于系统,并且您必须在启动参数中使用/3GB才能获得它),而每个进程都有4GB的空间,但Windows或.NET FX对不执行特殊操作的进程强制执行1GB的限制(SQL和Exchange除外)。 - Nic Wise
2
测试它的简单方法:在循环中分配内存,看看何时出现内存不足错误。对我来说,在32位系统上始终是大约750-800MB。 - Nic Wise

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