我有以下代码:
const int bufferSize = 1024 * 1024;
var buffer = new byte[bufferSize];
for (int i = 0; i < 10; i++)
{
const int writesCount = 400;
using (var stream = new MemoryStream(writesCount * bufferSize))
{
for (int j = 0; j < writesCount; j++)
{
stream.Write(buffer, 0, buffer.Length);
}
stream.Close();
}
}
我在 32 位机器上运行。
第一次迭代完成得很好,然后在下一次迭代中,我在 new
MemoryStream
.
尽管有 using
语句,为什么之前的 MemoryStream
内存没有被回收?如何强制释放 MemoryStream
使用的内存?
最佳答案
我不认为问题是垃圾收集器没有完成它的工作。如果 GC 面临内存压力,它应该运行并回收您刚刚分配的 400 MB。
这更有可能是因为 GC 没有找到连续的 400 MB block 。
Rather, an “out of memory” error happens because the process is unable to find a large enough section of contiguous unused pages in its virtual address space to do the requested mapping.
您应该阅读 Eric Lippert 的博客条目 "Out Of Memory" Does Not Refer to Physical Memory
您最好同时执行以下两项。
- 重用您分配的内存块(为什么要创建另一个大小完全相同的内存块)
- 分配更小的 block (小于 85KB)
在 Dotnet 4.5 之前,Dotnet 构造了两个堆,小对象堆 (SOH) 和大对象堆 (LOH)。参见 Large Object Hearp Improvements in .NET 4.5由布兰登布雷。您的 MemoryStream
正在 LOH 中分配,并且在该过程的持续时间内没有被压缩(碎片整理),这使得多次调用分配这么大的内存更有可能抛出 OutOfMemoryException
The CLR manages two different heaps for allocation, the small object heap (SOH) and the large object heap (LOH). Any allocation greater than or equal to 85,000 bytes goes on the LOH. Copying large objects has a performance penalty, so the LOH is not compacted unlike the SOH. Another defining characteristic is that the LOH is only collected during a generation 2 collection. Together, these have the built-in assumption that large object allocations are infrequent.
关于c# - 如何强行释放MemoryStream占用的内存?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12002443/