鉴于两台PC
更新1 - 有趣的是,将T的属性数量减少两倍没有任何变化,OOM发生的集合中的Ts数量保持不变...
采取平均低频率,我只是没有他们的手。
任何人都可以向我解释一下,为什么在第一台PC上运行完全正常的代码在第二台PC上运行失败100%的时候出现OutOfMemoryException?考虑到第二台PC成本高出3倍,这真的很烦人。
我不能在这里发布整个代码,但它非常简单 - 一个List用T填充,其中T是一个具有5个整数属性的CLR对象。第一台PC处理25M对象没问题(这就是我所看到的,它可能可以处理更多),而第二台PC处理大约。 16.5M记录。我知道单个对象内存限制,但它真正得到的是它如何在两个相当现代的PC之间偏离这么多(50%++)?
答案 0 :(得分:3)
问题严重不足,但我可以对其进行逆向工程。首先,你可以用尽内存的唯一方法是使用结构列表而不是类。这使得结构大小为4 * 5 = 20个字节。在1650万个元素中,您需要一个用于List<>的内部数组。具有至少20 x 16.5 = 330 MB的连续虚拟内存。下一个分配将要求双倍大小,660兆字节。在32位进程中很难实现。 OOM的风险与该规模非常接近。
问题在于您需要 continguous 分配。换句话说,虚拟内存地址空间中未使用的空洞至少为660兆字节。麻烦的是VM空间需要由代码和数据共享。代码是这里常见的麻烦制造者。一个DLL加载到一台机器而不是另一台机器上。像英特尔的铲刀,供应商或病毒扫描仪。 DLL具有可能非常笨拙的首选加载地址,将可用地址空间分成两个较小的部分。这些部分的总和仍然足够大,但没有留下足够大的空洞来适应660 MB的分配。
这是一个称为“地址空间碎片”的一般问题。它始终是OOM的第一个原因,消耗所有2千兆字节的可用地址空间非常困难。这只能通过进行非常小的分配来实现。
您可以采取一些非常简单的方法来解决此问题:
答案 1 :(得分:1)
这可能听起来很奇怪,但很容易排除。使用memory profiler并注意泄漏源。
我能找出低规格硬件的唯一方法是生存,而高失败则是内存碎片。 GC
并不擅长这一点。
答案 2 :(得分:0)
将构建平台设置为x64
(默认设置为Any Platform)已解决了我的问题。我尝试了一些好的食谱,包括gcAllowVeryLargeObjects
和强制x86,但无济于事。