【问题标题】:When and how is the .NET managed heap getting swapped?.NET 托管堆何时以及如何被交换?
【发布时间】:2011-06-10 01:04:09
【问题描述】:

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

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

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

IMO 这个问题对所有生产环境都很重要,可能会处理更大的数据集。不知何故,知道系统宁愿在这种情况下(通过交换)显着减慢速度而不是简单地抛出 OOM 感觉更“安全”。至少,它应该是确定性的,对吧?

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

【问题讨论】:

  • “直到物理地址空间”不是指那个进程的虚拟地址空间吗?
  • 您的程序设置为 AnyCPU 还是 32BitOnly? 64 位程序中的内存不足应该不会轻易发生。我希望计算机在此之前很久就会由于过度交换而停止运行。
  • 你是对的:“虚拟地址空间”的意思。是的,程序编译成 32 位应用程序,在 Win7 上运行 WOW。

标签: c# .net out-of-memory heap-memory swap


【解决方案1】:

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

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

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

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

【讨论】:

  • “如果它在虚拟内存地址空间中找不到适合请求的内存分配的空洞,则 HeapAlloc() 调用失败,CLR 生成 OOM。” - 但为什么黑客不是分页比?至少应该,如果虚拟空间还没有完全用完,但找不到其他 RAM?
  • 两个非常不同的东西。当需要找到物理内存空间时,就会发生分页。内存。内存分配发生在虚拟内存中。无论安装了多少 RAM,一个 32 位进程都有 2 GB。所有进程分配的所有虚拟内存的总和仅受页面文件限制,不受 RAM 限制。
  • 那么 2GB(64 位上的一些 TB)只是理论上的限制?内存管理器交换直到为进程保留的页面文件 part 的大小被填满?如果该部分甚至适合 RAM,它甚至根本不交换?这将回答问题
  • 只有最后一条评论是准确的。我会推荐“Windows Internals”以获得更多洞察力。
  • 好吧,其中很大一部分将被文件系统缓存使用。但是,是的,如果您希望能够运行需要 32GB 或更多的进程,那么您需要那么多的页面文件。默认设置是 RAM 大小的 1.5 倍,允许它增长。对于分页文件大小调整,请在 superuser.com 上提问
猜你喜欢
  • 2014-05-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-14
  • 2015-02-12
  • 2011-02-25
  • 2011-10-01
  • 2011-08-28
相关资源
最近更新 更多