我有 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();
}

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

没有正确的解决方案

其他提示

如果有十条线程中打开文件为您的代码显示,那么你必须在任何一个时间最多十个未予处置的FileStream对象。是的文件流的确实有一个内部缓冲区,你在你的代码“BigBufferSizeInBytes”指定尺寸。能否请您透露确切的价值?如果这是足够大的(例如,〜100MB),那么它很可能是问题的根源。

默认情况下(即,当没有指定时结构的号码),该缓冲液是4kB的,这是通常对于大多数应用精细。一般来说,如果你真的关心磁盘的写入性能,那么你可能会增加这一个一对夫妇100KB的的,但不多。

然而,对于特定应用这样做将没有多大意义,因为该缓冲器永远不会包含比你写进去的16-30字节越多,你的Dispose()之前FileStream对象。

要回答你的问题,抛出一个OutOfMemoryException异常,只有当请求的内存不能分配 GC运行后的。同样,如果缓冲区非常大,则系统可以有足够的内存留,只是没有一个连续块。这是因为大的对象堆从不压实。

我已经提醒人们这一个了几次,但的大对象堆可以抛出该异常相当subtially,当看似你有可用内存pleanty或应用程序正在运行确定。

在做几乎exactally当我碰到的这个问题相当频繁你的discribing这里。

您需要发布更多的代码的正确回答这个问题。不过,我猜它可能还涉及到一个潜在的问题万圣节的(鬼Dooky)

您缓冲到你正在阅读的也可能是问题(有关大再次对象堆)也再次,你需要把更多的细节这是怎么回事在那里的循环。我刚钉了最后的bug我有这几乎是相同的(我执行许多平行的哈希更新的问题都需要独立的国家跨读取的输入文件的维护)......

OOP!只是在滚动,并注意到“BigBufferSizeInBytes”,我倾向于大对象堆再次...

如果我是你,(这是非常困难的,因为缺乏上下文的),我会提供一个小的调度“的mbuf”,在那里你在复制出来,而不是让所有的disperate线程的单独跨阅读你的大支持数组...(即很难不引起insadential分配非常微妙的代码语法)。

缓冲器通常不会分配的FileStream内部。也许问题是线“写作成千上万的小缓冲区” - 你真的这样想?通常你重新使用缓冲区很多很多,多次(即在不同的呼叫到读/写)。

另外 - 这是一个单一的文件?一个单一的FileStream不能保证是线程安全的......所以,如果你不是做同步,预期混乱。

这些限制可能是由底层操作系统引起的,而 .NET Framework 无法克服这些限制。

我无法从您的代码示例中推断出您是否同时打开大量这些 FileStream 对象,或者按顺序快速打开它们。使用“using”关键字将确保文件在 fs.Write() 调用后关闭。关闭文件不需要 GC 循环。

FileStream 类实际上适合对文件进行顺序读/写访问。如果您需要快速写入大文件中的随机位置,您可能需要考虑使用虚拟文件映射。

更新:看来虚拟文件映射要到4.0才会在.NET中正式支持。您可能想查看此功能的第三方实现。

戴夫

我遇到类似的东西,不知道如果你牵制你的问题的根源在哪里?

我的代码做了相当多的文件之间进行复制,传递不同的字节文件之间有不少兆。我注意到的是,尽管进程的内存使用保持在合理范围内,系统内存分配的复制过程中拍摄了太高了 - 比正被我的进程等等。

我跟踪这个问题下到FileStream.Write()调用 - 当这条线取出,内存使用情况似乎跟预期。我BigBufferSizeInBytes是默认(4K),我看不到任何地方,这些可能是收集...

任何你而你的问题看会感激地收到发现!

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top