首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何尽可能高效地处理大量并发磁盘写请求

如何尽可能高效地处理大量并发磁盘写请求
EN

Stack Overflow用户
提问于 2011-09-15 03:21:44
回答 4查看 3.1K关注 0票数 9

假设下面的方法被.net 4应用程序中的不同线程调用了数千次。处理这种情况的最好方法是什么?我知道磁盘是这里的瓶颈,但我希望WriteFile()方法能快速返回。

数据大小可以高达几MB。我们是在谈论线程池、第三方公共关系还是类似的东西?

代码语言:javascript
运行
复制
public void WriteFile(string FileName, MemoryStream Data)
{
   try
   {
      using (FileStream DiskFile = File.OpenWrite(FileName))
      {
         Data.WriteTo(DiskFile);
         DiskFile.Flush();
         DiskFile.Close();
      }
   }
   catch (Exception e)
   {
      Console.WriteLine(e.Message);
   }
}
EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2011-09-15 03:38:01

既然您说文件不需要按顺序或立即写入,那么最简单的方法就是使用Task

代码语言:javascript
运行
复制
private void WriteFileSynchronous(string FileName, MemoryStream Data)
{
    Task.Factory.StartNew(() => WriteFileSynchronously(FileName, Data));
}

private void WriteFileSynchronous(string FileName, MemoryStream Data)
{
    try
    {
        using (FileStream DiskFile = File.OpenWrite(FileName))
        {
            Data.WriteTo(DiskFile);
            DiskFile.Flush();
            DiskFile.Close();
        }
    }

    catch (Exception e)
    {
        Console.WriteLine(e.Message);
    }
}

TPL在内部使用线程池,即使对于大量任务也应该相当有效。

票数 3
EN

Stack Overflow用户

发布于 2011-09-15 03:29:04

如果你想快速返回,而不是真正关心操作是否同步,你可以在内存中创建某种Queue,你将在其中放置写请求,当队列没有填满时,你可以快速从方法返回。另一个线程将负责调度Queue和写入文件。如果您的WriteFile被调用并且队列已满,您将不得不等待,直到您可以排队,并且执行将再次变得同步,但是通过这种方式,您可能有一个很大的缓冲区,所以如果处理文件写入请求不是线性的,而是更尖峰的(写入文件调用高峰之间的暂停),这样的改变可以被视为您的性能的改进。

更新:为你做了一张小照片。请注意,瓶颈总是存在的,您所能做的就是使用队列优化请求。请注意,队列是有限制的,因此当它被填满时,您无法将队列文件安装到中,您必须等待,以便缓冲区中也有空闲空间。但是对于图片中呈现的情况(3个存储桶请求),很明显你可以快速地将存储桶放入队列并返回,而在第一种情况下,你必须一个接一个地执行并阻塞执行。

请注意,你永远不需要一次执行许多IO线程,因为它们都将使用相同的瓶颈,如果你尝试大量并行,你只会浪费内存,我相信2- 10个线程顶部将轻松地占用所有可用的IO带宽,并将限制应用程序内存的使用。

票数 6
EN

Stack Overflow用户

发布于 2011-09-15 07:49:53

如果数据传入的速度快于您记录它的速度,那么您就有了一个真正的问题。一种生产者/消费者设计,让WriteFile只是把东西扔到ConcurrentQueue或类似的结构中,并且有一个单独的线程为队列提供服务,效果很好……直到队列填满。如果您正在谈论打开50,000个不同的文件,那么备份速度会很快。更不用说每个文件可能有几兆字节的数据,这将进一步限制队列的大小。

我遇到过一个类似的问题,我通过将WriteFile方法附加到一个文件中解决了这个问题。它写入的记录有一个记录号、文件名、长度,然后是数据。正如Hans在对原始问题的评论中指出的那样,写入文件很快,打开文件很慢。

我的程序中的第二个线程开始读取WriteFile正在写入的文件。该线程读取每个记录头(编号、文件名、长度),打开一个新文件,然后将数据从日志文件复制到最终文件。

如果日志文件和最终文件位于不同的磁盘上,这会工作得更好,但它仍然可以在单个磁盘轴上很好地工作。不过,它肯定会锻炼你的硬盘。

它的缺点是需要2倍的磁盘空间,但由于2TB的硬盘低于150美元,我认为这不是什么大问题。总体来说,它的效率也低于直接写入数据(因为您必须处理两次数据),但它的好处是不会导致主处理线程停止。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7421797

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档