使用字节数组时堆积碎片

我有一个C#4.0应用程序(单个生产者/单个消费者),它以块的forms传输大量数据。 虽然没有新的内存分配,但一段时间后内存不足。

我使用Redgate内存分析器分析内存,那里有很多可用内存。 它说由于碎片化而无法使用空闲内存。

我使用阻塞集合作为缓冲区和字节数组作为成员:

BlockingCollection segments = new BlockingCollection(8); // producer: segments.Add(buffer); // consumer: byte[] buffer = _segments.Take(); 

如何避免托管内存碎片?

您可能遇到了大对象堆问题 – 大于85,000字节的对象被放置在未压缩的大对象堆上,这可能导致奇怪的内存不足情况。 虽然.NET 4中的性能显然已得到改善,但它还远非完美。 解决方案是基本上使用您自己的缓冲池,其中包含一些静态分配的内存块并重用这些内存。
SO上有很多问题。

更新 :Microsoft提供缓冲区管理器作为WCF堆栈的一部分。 codeproject上还有一个 。

你的byte []数组有多长? 它们落入小物体或大物体堆中吗? 如果你遇到内存碎片,我会说他们属于LOH。

因此,您应该重用相同的字节数组(使用池)或使用较小的块。 LOH从未被压缩,因此它可能变得非常分散。 可悲的是,没有办法解决这个问题。 (除了知道这个限制并避免它)

GC不会为您压缩大对象堆,您仍然可以以编程方式压缩它。 以下代码段说明了如何实现此目的。

 GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce; GC.Collect();