[英]OutOfMemoryException in C#
此代码会导致某种内存泄漏。 我认为这是由new byte[]
引起的。 但是GC是否应避免这种情况? 如果程序运行足够长时间,则代码将导致OutOfMemoryException
using (var file = new FileStream(fileLoc, FileMode.Open))
{
int chunkSize = 1024 * 100;
while (file.Position < file.Length)
{
if (file.Length - file.Position < chunkSize)
{
chunkSize = (int)(file.Length - file.Position);
}
byte[] chunk = new byte[chunkSize];
file.Read(chunk, 0, chunkSize);
context.Response.BinaryWrite(chunk);
}
}
几乎可以肯定的问题是,您正在重复分配新数组,并且在内存中它们被分配为连续的块,因此我可以理解它是如何通过它咀嚼的。
如何稍微重新调整一下内容,以便仅创建一次缓冲区然后再使用它,除非您进入所需的块大小小于标准块大小的情况。
using (var file = new FileStream(fileLoc, FileMode.Open)) {
int chunkSize = 1024 * 100;
byte[] chunk = new byte[chunkSize];
while (file.Position < file.Length) {
if (file.Length - file.Position < chunkSize) {
chunkSize = (int)(file.Length - file.Position);
chunk = new byte[chunkSize];
}
file.Read(chunk, 0, chunkSize);
context.Response.BinaryWrite(chunk);
}
}
我可以建议您尝试使用较小的缓冲区吗?
问题可能是您重复分配了一个大于85000字节的内存块,该内存块进入一个不幸的是从未压缩过的特殊堆(大对象堆)!
有关大对象堆如何工作的详细说明,请参见此处 。 不幸的是,这可能导致严重的堆碎片,并最终导致内存不足错误,如您所描述的那样(请参阅此处: loh碎片会导致OutOfMemory异常 )
如果您分配较小的块(小于85,000字节),那么它们将分配在常规堆上,那么GC将能够执行压缩,并且几乎可以肯定,您的问题将消失。 我也强烈建议您按照@Nanhydrin的建议修改您的代码,因为这样可以避免重复分配,并且应该会表现得更好
我不能完全确定“运行足够长的时间”是什么意思,但是该代码分配的数组至少为100 KB(如果文件更大,则可能更大)。 它本身可能不会导致故障,但是在只有32 MB虚拟地址空间的环境中,这是相当大的内存分配。 如果其中许多并行运行,则可以很容易地将其乘以一个相对较高的内存使用率,在这种情况下,您可能会看到OutOfMemoryException
。
假设context.Response
是一个HttpResponse
,看起来您只是试图将文件的内容写入HTTP响应,在这种情况下,您可以使用以下类似方法更有效地做到这一点:
using (var file = new FileStream(fileLoc, FileMode.Open))
{
CopyStream(file, context.Response.OutputStream);
}
请参见在两个Stream实例之间进行复制的最佳方法-C#中的CopyStream
实现,该实现以较小的块为单位逐位复制数据,而不是尝试一次读取整个文件。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.