何时以及如何交换.NET托管堆?

use*_*238 5 .net c# heap swap out-of-memory

我的小压力测试在一个循环中分配随机长度数组(每个100..200MB),在64位Win7机器和32位XP(在VM中)上显示不同的行为.两个系统首先通常分配尽可能多的数组,以适应LOH.然后LOH变得越来越大,直到可用的虚拟地址空间被填满.到目前为止的预期行为.但是 - 在进一步的请求中 - 两者的行为都不同:

在Win7上抛出一个OutOfMemoryException(OOM),在XP看起来,堆增加甚至交换到磁盘 - 至少没有抛出OOM.(不知道,如果这可能与在虚拟盒中运行的XP有关.)

问题:运行时(或操作系统?)如何决定是否为托管内存分配请求,如果它太大而无法分配,生成OOM或大对象堆增加 - 最终甚至交换到磁盘?如果它被交换,OOM什么时候出现?

IMO这个问题对所有生产环境都很重要,可能涉及更大的数据集.不知何故,感觉更"安全",系统在这种情况下(通过交换)会比简单地抛出OOM而显着减速.至少,它应该以某种方式确定性,对吧?

@Edit:该应用程序是一个32位应用程序,因此在Win 7上以32位模式运行.

Han*_*ant 8

正常规则适用,Windows内存管理器不会对托管进程进行不同的处理.内存块的最终来源是Windows内存管理器.如果它无法在虚拟内存地址空间中找到一个空洞以满足所请求的内存分配,那么它将无法通过VirtualAlloc()调用而CLR生成OOM.

对于交换行为也是如此,如果需要RAM中的页面来映射其他进程的页面甚至同一进程的页面,那么它们将被换出.这与OOM无关.

您不能假设它在XP上的工作方式与在Win7 x64上完全相同.在构建针对AnyCPU的程序时,在x64上获取OOM非常不寻常,64位操作系统具有非常大的虚拟内存地址空间.上限由页面文件的最大大小设置.32位程序将在WOW仿真层中运行,如果使用Editbin.exe设置LARGEADDRESSAWARE选项位,它可以具有4 GB的地址空间.

您可以使用SysInteral的VMMap实用程序来查看进程的地址空间是如何被分割的.

  • 只有最后一条评论是准确的.我推荐"Windows Internals"以获得更多洞察力. (3认同)
  • 两个*非常*不同的东西。当需要找到“物理”内存空间时,就会发生分页。内存。内存分配发生在“虚拟”内存中。无论安装了多少 RAM,32 位进程都有 2 GB。所有进程分配的所有虚拟内存的总和仅受页面文件的限制,不受 RAM 的限制。 (2认同)
  • 好吧,其中很大一部分将被文件系统缓存使用。但是,是的,如果您希望能够运行需要 32GB 或更多内存的进程,那么您就需要那么多的分页文件。默认设置是 RAM 大小的 1.5 倍,允许其增长。对于分页文件大小调整,请在 superuser.com 上提问 (2认同)