我发现我的应用程序比预期更快地耗尽内存。它创建了许多大小为几兆字节的字节数组。然而,当我使用vmmap查看内存使用情况时,.NET为每个缓冲区分配的空间比实际需要的要多得多。确切地说,当分配一个9兆字节的缓冲区时,.NET会创建一个16兆字节的堆。剩下的7兆字节不能用来创建另一个9兆字节的缓冲区,因此.NET会再次创建一个16兆字节的堆。所以每个9MB的缓冲区浪费了7MB的地址空间!
下面是一个示例程序,在32位.NET 4中分配了106个缓冲区后抛出OutOfMemoryException异常:
下面是一个示例程序,在32位.NET 4中分配了106个缓冲区后抛出OutOfMemoryException异常:
using System.Collections.Generic;
namespace CSharpMemoryAllocationTest
{
class Program
{
static void Main(string[] args)
{
var buffers = new List<byte[]>();
for (int i = 0; i < 130; ++i)
{
buffers.Add(new byte[9 * 1000 * 1024]);
}
}
}
}
请注意,您可以将数组的大小增加到16 * 1000 * 1024,而仍然可以在耗尽内存之前分配相同数量的缓冲区。
VMMap显示如下:
还要注意托管堆的总大小和已提交大小之间几乎有100%的差异。(1737MB vs 946MB)。
在.NET上是否有可靠的方法来解决这个问题?即,我可以强制运行时分配不超过我实际需要的数量,或者可以用于多个连续缓冲区的更大的托管堆吗?
new byte[7 * 9 * 1000 * 1024]
),这相当接近64M。 - beerboy