【问题标题】:OutOfMemory Exception on two PCs [closed]两台 PC 上的 OutOfMemory 异常 [关闭]
【发布时间】:2013-04-07 22:17:43
【问题描述】:

给定两台电脑

  1. Core i5 第三代 4GB RAM(戴尔 Optiflex 7010)
  2. Core i7 第二代 16GB RAM(三星 700G7C)

更新 1 - 有趣的是,将 T 的属性数量减少两倍并没有改变,集合中发生 OOM 的 T 数量保持不变......

取平均低频,我只是手头没有。

谁能向我解释一下,为什么第一台 PC 上运行良好的代码在第二台 PC 上 100% 失败并出现 OutOfMemoryException?考虑到第二台电脑的成本要高出 3 倍,这真的很烦人。

我不能在这里发布整个代码,但它真的很简单 - 一个 List 填充有 T,其中 T 是一个具有 5 个 Integer 属性的 CLR 对象。第一台 PC 处理 2500 万个对象没问题(这就是我所看到的,它可能可以处理更多),而第二台 PC 大约死了。 1650 万条记录。我知道单个对象内存限制,但它真正让我明白的是它如何在两台相当现代的 PC 之间偏离这么多(50%++)?

【问题讨论】:

  • 相同版本的 Windows(32 位/64 位)?虚拟内存大小呢?页面文件的大小比 RAM 的大小更重要。
  • 一个运行 64 位,另一个运行 32 位通常是罪魁祸首。
  • Win7 64bit with latests updates,我没有检查虚拟内存大小,我该怎么做?
  • @Peter,我有 90% 的把握两者都在 64 位平台上运行,肯定是第二台 PC,但它表现出更差的性能。

标签: .net memory memory-management


【解决方案1】:

这可能听起来很奇怪,但很容易排除。使用memory profiler 并注意泄漏源。

我能找出低规格硬件存活而高规格硬件失败的唯一方法是内存碎片。 GC 不擅长这个。

【讨论】:

  • 我在没有其他应用程序运行的情况下运行我的测试,所以理论上碎片应该不是问题。我可以在两台机器上使用 ANTS 内存分析器来确定这两台机器上巨大的性能差异的原因吗?你能建议我首先看什么吗?
  • @user1514042:无论如何,没有任何线索,第一步将是内存分析。 ANTS 有免费试用期,因此您应该在此期间解决问题或购买许可证以继续使用它。所以安装时要快。除非您正在寻找特殊模式,否则在有问题的机器上安装就足够了。在此处发布结果,以便我们提供更多帮助。
【解决方案2】:

将构建平台设置为x64(默认设置为任何平台)解决了我的问题。我尝试了一些不错的方法,包括 gcAllowVeryLargeObjects 和强制 x86,但无济于事。

【讨论】:

    【解决方案3】:

    这个问题的文档严重不足,但我可以对其中的一些问题进行逆向工程。首先,内存不足的唯一方法是使用结构列表而不是类。这使得结构大小为 4 * 5 = 20 字节。对于 1650 万个元素,您需要一个用于 List 的内部数组,该数组至少具有 20 x 16.5 = 330 兆字节的连续虚拟内存。下一次分配将要求双倍大小,即 660 兆字节。这在 32 位进程中很难实现。 OOM 的风险与该大小非常接近。

    问题在于您需要连续分配。换句话说,虚拟内存地址空间中至少有 660 兆字节的未使用空洞。问题是VM空间需要由代码和数据共享。代码是这里常见的麻烦制造者。一个在一台机器上而不是另一台机器上加载的 DLL。就像来自英特尔、供应商或病毒扫描程序的铲子一样。 DLL 有一个可能非常尴尬的首选加载地址,将可用地址空间分成两个较小的部分。这些部分的总和仍然足够大,但没有留下足够大的孔来容纳 660 MB 的分配。

    这是一个被称为“地址空间碎片”的普遍问题。它始终是 OOM 的第一个原因,很难消耗所有 2 GB 的可用地址空间。这只能通过进行非常小的分配来实现。

    你可以做几个非常简单的事情来解决这个问题:

    • 摆脱那台机器上的铲子,使用 SysInternals 的 VMMap 实用程序看看是否有效
    • 使用类而不是结构。现在 List 元素大小只有 4 个字节而不是 20 个
    • 使用 List.Capacity 属性。这可以减少您在列表增长时多次重新分配内部数组而产生的地址空间碎片。只要你有一个好的初步猜测。
    • 你有很好的硬件,使用它。将 EXE 项目上的 Target platform 设置更改为 AnyCPU。 64 位进程具有大量地址空间,很难全部使用。
    • 您可以使用 EXE 上的 /LARGEADDRESSAWARE 选项运行 Editbin.exe。现在,您的 32 位进程在 64 位操作系统上将拥有 4 GB 的地址空间。

    【讨论】:

    • 我正在使用课程,汉斯;) 不过感谢您的回复。
    • 好吧,老鼠。您需要使用内存分析器。最后 3 颗子弹还是不错的。
    猜你喜欢
    • 2011-06-23
    • 2012-08-19
    • 2015-10-19
    • 1970-01-01
    • 2018-09-05
    • 1970-01-01
    • 2015-07-28
    • 2018-06-18
    相关资源
    最近更新 更多