大对象堆碎片化,数组问题

9
我正在使用C#编写一个分析应用程序,需要处理大量的内存。我使用ANTS Memory Profiler 7.4优化我的内存管理。在这个过程中,我意识到我使用(并且需要)的所有double[,]数组都被放置在LOH上,尽管其中最大的数组只有约24,000字节。据我所知,对象不应该在85,000字节之前放置在那里。问题是,由于我有数千个这些double[,]数组的实例,因此我有很多内存碎片(我的总内存使用量的约25%是无法使用的空闲内存)。其中一些存储在LOH上的数组甚至只有1,036字节大小。问题是,有时我必须执行更大的分析,然后由于LOH碎片而导致内存大量丢失,最终出现了内存不足异常。
请问,为什么会发生这种情况,尽管它根据定义不应该是一个大对象?
我的应用程序的内存快照如下图所示: Memroy snapshot of my application using ANTS Memory Profiler 即使是这样小的double数组(数组中仅有70个元素),也受到这种情况的影响: small double arrays are also affected by this (only 70 elements in the array)

请看这个答案:https://dev59.com/_XRB5IYBdhLWcg3wN08P! - mtijn
我看到了,但首先我这里不使用字符串,并且关于双数组的答案也不适用于我的问题,因为我的许多LOH上的double[,]数组甚至没有6个项目。所以这真的让我感到困惑。但还是谢谢你的回答。我之前已经看过那篇文章,但它并没有完全解决我的问题。 - Oliver Bernhardt
1个回答

4

将双精度数组放入LOH的阈值大小比其他类型要低得多。原因是LOH上的项目始终是64位对齐的,而双精度浮点数非常适合64位对齐。

请注意,这仅影响运行在32位下的程序。运行在64位下的程序具有始终对齐于64位边界的对象,因此不会使用LOH启发式算法来处理64位程序。

阈值大小为1000个双精度浮点数。

另请参见https://connect.microsoft.com/VisualStudio/feedback/details/266330/


正如我所说,它也会影响大小仅为6个条目的double[,]数组。因此,位于LOH上的数组是一个double[2,3]数组,但它仍然最终位于LOH上(与其他更大的double[,]数组一起)。但是我的大多数数组(约90%)不超过1000个double的阈值。 好的,我在截图中显示的那些超出了此限制,但大部分都没有超过。那么它们怎么样?为什么它们最终会到那里? - Oliver Bernhardt
即使在仅分配一个数组的简单程序中,这种情况是否也会发生?想知道是否有任何奇怪的东西触发了这种行为。 - Matthew Watson
是的...似乎类型为double[,](多维)的数组无论大小都会被放置在LOH上。有人知道如何防止这种情况吗?因为我经常使用它们,而且我不想完全重新设计整个项目。 - Oliver Bernhardt
2
在.NET Framework 4.6中,多维双精度数组遵循相同的规则。 Console.WriteLine(GC.GetGeneration(new double [31,31])); 输出0,并且Console.WriteLine(GC.GetGeneration(new double [32,32]));输出2。 - Antosha

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接