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

C# .NET托管堆何时以及如何交换?,c#,.net,heap,out-of-memory,swap,C#,.net,Heap,Out Of Memory,Swap,我的小型压力测试在循环中分配随机长度数组(每个100..200MB),在64位Win7机器和32位XP(在VM中)上显示了不同的行为。这两个系统通常首先分配尽可能多的阵列,以适应LOH。然后LOH变得越来越大,直到可用的虚拟地址空间被填满。到目前为止的预期行为。但是,在进一步的请求中,两者的行为都不同: 在Win7上抛出OutOfMemoryException(OOM),而在XP上,堆似乎增加了,甚至交换到了磁盘上——至少没有抛出OOM。(不知道这是否与XP在虚拟机中运行有关。) 问题: 运行时

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

在Win7上抛出OutOfMemoryException(OOM),而在XP上,堆似乎增加了,甚至交换到了磁盘上——至少没有抛出OOM。(不知道这是否与XP在虚拟机中运行有关。)

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

IMO这一问题对于所有生产环境都很重要,可能会处理更大的数据集。不知何故,它感觉更“安全”知道,系统宁愿在这种情况下急剧放缓(通过交换),而不是简单地抛出OOM。至少,它应该是决定性的,对吗


@编辑:该应用程序是32位应用程序,因此在Win7上以32位模式运行

根据正常规则,Windows内存管理器不会对托管进程进行不同的处理。内存块的最终来源是Windows内存管理器。如果在虚拟内存地址空间中找不到适合请求的内存分配的洞,则会导致VirtualAlloc()调用失败,CLR将生成OOM

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

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


您可以使用SysInteral的VMMap实用程序查看进程的地址空间是如何划分的。

“直到物理地址空间”您不是指该进程的虚拟地址空间吗?您的程序设置为AnyCPU还是仅32位?64位程序中的内存不足不应轻易发生。早在那之前,我就预计计算机会因为过度交换而死机。你说得对:“虚拟地址空间”就是这个意思。是的,prog编译成一个32位的应用程序,在Win7上运行WOW。“如果它不能在虚拟内存地址空间中找到一个洞来满足请求的内存分配,那么它会失败heapolloc()调用,CLR生成OOM。”-但是为什么黑客不这么做呢?至少应该是这样,如果虚拟空间还没有完全用完,但找不到其他RAM,这是两件截然不同的事情。当需要找到物理内存空间时,会发生分页。内存内存分配发生在虚拟内存中。无论安装了多少RAM,32位进程都有2G的内存。所有进程分配的所有虚拟内存的总和只受分页文件的限制,而不受RAM的限制。因此2GB(64位上的一些TB)只是理论上的限制?内存管理器交换,直到为进程保留的页面文件部分的大小被填满为止?如果那个部件能装进RAM,它甚至不能互换?这将回答问题,但最后的评论是准确的。我建议使用“Windows内部构件”来了解更多信息。最后一句话应该是:“如果进程的虚拟内存完全适合RAM,它甚至根本不交换?”