写入大量数据到文件时的缓存问题

5

当我写入一个超过2GB的大文件时,出现了问题。前1.4GB数据写入速度很快(100MB/s),但之后代码变得非常缓慢(0-2 MB/s)。

我的代码如下(简化版):

//FileOptions FILE_FLAG_NO_BUFFERING = (FileOptions)0x20000000;
    FileOptions fileOptions = FileOptions.SequentialScan;

    int fileBufferSize = 1024 * 1024;
    byte[] Buffer = new byte[32768];

    Random random = new Random();
    long fileSize = 2588490188;
    long totalByteWritten = 0;

    using (FileStream fs = File.Create(@"c:\test\test.bin", fileBufferSize, fileOptions))
    {
        while (totalByteWritten < fileSize)
        {
            random.NextBytes(Buffer);
            fs.Write(Buffer, 0, Buffer.Length);
            totalByteWritten += Buffer.Length;
            //Thread.Sleep(10);
        }
    }

我认为这与缓存问题有关,在“快速写入性能”期间,RAM使用量也会增加,当RAM使用量停止增长时,性能会下降。

我尝试过:

  • 更改为异步写入->没有显著变化

  • 更改数组缓冲区大小->没有显著变化

  • 更改fileBufferSize->没有显著变化,但是使用大缓冲区(约100MB)时,写入性能很快,当RAM使用量停止增长时,写入性能降为0,然后一段时间后回到100MB,似乎缓存缓冲区被“刷新”

  • fileOption更改为WriteThrough->性能始终很慢..

  • 在xx个循环之后添加fs.Flush(true)->没有显著变化

  • 取消注释Thread.Sleep(10)->写入速度始终很好.....这很奇怪


似乎thread.sleep有助于清除内存并将其转储到磁盘。你能测试一下你的硬盘写入速度吗?我认为在开始时,所有内容都被写入内存,直到内存满了,然后Windows页面文件和你的文件都会继续写入,因此性能会降低。但我可能错了 :) - Rafael Herscovici
系统上是否运行了某些反病毒软件,当 RAM 被填满并开始将数据写入磁盘后会降低性能? - Brian Swift
嗯,据我理解,在您的情况下,“FileOptions.SequentialScan”根本没有用处。这只在从磁盘中读取时很重要,而不是写入。就我所了解的情况,这只是一个简化的代码片段,所以我猜“random.NextBytes”只是您真实数据的占位符。真实数据来自哪里?收集真实数据可能是罪魁祸首吗? - Jens H
我会检查硬盘写入速度。并且没有杀毒软件,我已经在删除杀毒软件后进行了相同的测试。真实数据来自千兆以太网或对大文件的某些分析,random.NextBytes仅用作随机数据生成器。 - Becco
1个回答

0

它是否在尝试在完成上一个块的写入之前进行写入并陷入混乱?(似乎不太可能,但很奇怪的是Thread.Sleep应该加速它,这可能可以解释)。如果您修改使用语句内部的代码以锁定文件流会发生什么,像这样:

using (FileStream fs = File.Create(@"c:\testing\test.bin", fileBufferSize, fileOptions))
{
  while (fs.Position < fileBufferSize)
  {
    lock(fs) // this is the bit I have added to try to speed it up
    {
      random.NextBytes(Buffer);
      fs.Write(Buffer, 0, Buffer.Length);
    }
  }
}

编辑:我已经调整了您的示例代码,包括必需的while循环,以使其写入正确大小的文件。

顺便说一句,当我运行示例代码时,无论是否使用lock语句,它都非常快,并且添加睡眠会显著减慢速度。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接