English 中文(简体)
可能导致FileStream.Write()抛出OutOfMemoryException的原因?
原标题:
  • 时间:2009-02-16 10:08:11
  •  标签:

我有10个线程在随机位置向一个巨大的文件中写入成千上万个小缓冲区(每个缓冲区大小为16-30字节)。其中一些线程在FileStream.Write()操作时抛出OutOfMemoryException。

什么导致了OutOfMemoryException?要查找什么?

我是这样使用FileStream的(对于每个写入的项目-此代码从10个不同的线程运行):

using (FileStream fs = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite, BigBufferSizeInBytes, FileOptions.SequentialScan))
{
 ...
 fs.Write();
}

我怀疑在 FileStream 中分配的所有缓冲区都没有及时被 GC 释放。我不明白的是,为什么 CLR 不会在抛出异常之前运行 GC 循环并释放所有未使用的缓冲区?

问题回答

如果按照您的代码显示,有十个线程正在打开文件,那么您每次最多有十个未处理的FileStream对象。是的,FileStream确实具有内部缓冲区,其大小由您在代码中指定的“BigBufferSizeInBytes”决定。您能否披露确切的值?如果这足够大(例如~100MB),则很可能是问题的根源。

默认情况下(即在构建时没有指定数字),该缓冲区为4kB,对于大多数应用程序来说,这通常是可以的。一般来说,如果您真的关心磁盘写入性能,那么您可能会将其增加到几个100kB,但不要超过。

然而,对于您特定的应用程序来说,这样做并没有太多意义,因为在Dispose() FileStream对象之前,缓冲区永远不会包含多于16-30个字节的内容。

回答你的问题,当请求的内存不能在GC运行分配时,就会抛出OutOfMemoryException。再次说明,如果缓冲区真的很大,那么系统可能还有大量的内存可用,只是没有连续的块。这是因为大对象堆永远不会被压缩。

我已经几次提醒人们注意这件事了,但是当你似乎有足够的可用内存或应用程序正常运行时,大对象堆可以相当隐晦地抛出该异常。

我经常在做的事情和你描述的几乎完全一样时遇到这个问题。

您需要发布更多的代码才能正确回答这个问题。不过,我猜这也可能与潜在的万圣节问题有关(Spooky Dooky)

你从中读取的缓冲区可能也是问题(再次与大对象堆相关),还需要更多关于循环中正在发生的事情的详细信息。我刚刚解决了最后一个虚拟相同的错误(我正在执行许多并行的哈希更新,所有这些更新都需要在读取输入文件时维护独立状态)。

哦!我刚刚滚动查看了一下,注意到了“BigBufferSizeInBytes”,我又倾向于使用大对象堆了...

如果我是你的话,(由于缺乏上下文,这是极其困难的),我会提供一个小的分派 "mbuf",你可以在其中复制进和复制出,而不是让你所有分散的线程单独读取你的大型备份数组...(也就是说,这很难不使用非常微妙的代码语法引起意外分配)。

缓冲区通常不会在FileStream内分配。也许问题在于“写入数千个小缓冲区”的行——你是真的这么认为吗?通常情况下,您会多次重复使用缓冲区(即在不同的Read/Write调用中重复使用)。

另外 - 这是单独的文件吗?单个FileStream不能保证线程安全...因此,如果您不进行同步,请准备好混乱。

这些限制可能来自底层操作系统,.NET框架无法克服这些限制。

我从你的代码示例中无法推断出你是否同时打开了大量这些FileStream对象,还是按顺序快速打开它们。你使用的using关键字将确保文件在fs.Write()调用后关闭。没有需要关闭文件的GC周期。

FileStream类真正针对文件的顺序读/写访问。如果您需要快速写入大型文件中的随机位置,则可能需要考虑使用虚拟文件映射。

更新:虚拟文件映射在.NET中似乎直到4.0才获得官方支持。您可能需要查看第三方实现来实现此功能。

戴夫

我正在经历类似的事情,想知道您是否找到了问题的根源?

我的代码在文件之间进行了相当多的拷贝,并且在不同的字节文件之间传递了相当多的兆字节。我注意到,尽管进程内存使用保持在合理范围内,但系统内存分配在拷贝期间飙升得太高了,远远超过了我的进程使用的内存。

我已经追踪到问题出现在FileStream.Write()调用上 - 当删除此行时,内存使用情况似乎符合预期。我的BigBufferSizeInBytes是默认值(4k),我看不出任何地方可能会收集这些...

在查看您的问题时,您发现的任何事情都将不胜感激!





相关问题
热门标签