繁体   English   中英

在.NET中读取/写入磁盘的最快方法是什么?

[英]What's the fastest way to read/write to disk in .NET?

我有一个小程序,可以在磁盘上读写文件。 将其分解为最简单的级别,它从一个文件流中读取字节并将它们写入另一个文件流。 它履行其职责很好,但它不是最快的事情。

我已经看到其他应用程序可以以惊人的速度撕破一千兆字节或更多的读/写。 显然,他们的操作更接近金属,而不是一个小的.NET应用程序。

用于流入/流出磁盘的最有效的.NET API是什么? 什么win32 API可用(并且值得p /调用)以便快速访问磁盘?

快速文件I / O不是关于您所进行的特定API调用,而是关于如何构建应用程序以使用I / O.

例如,如果要以顺序方式在单个线程上执行所有I / O操作

  1. 将块读入内存
  2. 以某种方式在内存中处理块
  3. 将块写入文件
  4. 重复直到完成......

您是在单个线程的处理循环中瓶颈系统的I / O带宽。 另一种更复杂的设计是多线程应用程序以最大化吞吐量并避免等待时间。 这允许系统同时利用CPU和I / O控制器带宽。 典型的设计看起来像这样:

  1. 一个(或多个)工作线程从磁盘读取数据并将它们添加到共享输入队列
  2. 一个(或多个)工作线程从共享输入队列中读取块,处理它们并将它们添加到共享输出队列
  3. 一个(或多个)工作线程读取已从共享输出队列中阻止的处理,并将它们写入相应的输出文件。

这不是一个容易设计的简单架构,需要花费很多心思来避免创建内存中的锁争用,或者使用并发I / O请求来压倒系统。 您还需要提供控制元数据,以便不在线程的调用堆栈上管理输出处理的状态,而是在输入/输出工作队列中管理。 您还必须确保以正确的顺序转换和写入输出,因为对于多线程I / O,您无法确保按保证顺序将工作放在输入队列中。 它很复杂 - 但它是可能的,并且它可以在串行方法上产生巨大的吞吐量差异。

如果您真的有时间并希望从系统中挤出每一盎司的性能,您还可以使用I / O完成端口 (相对较低级别的API)来最大化吞吐量。

祝好运。

.NET文件支持足够快(与本机Win32功能相当)。 有几个选项可以帮助您提高绩效:

  1. 如果您的读/写是顺序的,请通过应用适当的策略来帮助缓存管理器 - 在实例化FileStream时提供RandomAccess或SequentalScan
  2. 考虑使用更大的内存缓冲区来存储读取数据
  3. 如果复制许多小文件,可以先将多个文件一次读入内存缓冲区(参见2),然后将文件写入磁盘
  4. 如果源和目标流位于不同的位置(即,不在同一个硬盘驱动器上,可能是网络上的一个文件,另一个在本地硬盘驱动器上等),则可以使用异步模式加速,使用BeginRead读取数据,然后使用BeginWrite写入数据,并在写入数据时使用BeginRead读取下一个数据块。
  5. 如果您仍然认为性能不够(但是从我的测试中它可以比内部Windows副本等同甚至更快),您可以使用CopyFileEx Win32函数(但此函数适用于文件,而不是流)。

您是否已分析应用程序以确定磁盘I / O是否是瓶颈?

您运行此类型的硬件是什么类型的? 什么是硬件配置?

在.NET中,您可以尝试使用System.IO.File命名空间。

对于Win32函数,您可以尝试CreateFile,WriteFile,ReadFile系列。

一个例子:

http://msdn.microsoft.com/en-us/library/bb540534(VS.85).aspx

这绝对不是切割和干燥。 这都是关于测试和测量的。

具有合适缓冲区大小的BinaryReaderBinaryWriter非常快。 如果您正在阅读结构, 本文中描述的不安全方法将使您快速阅读,并且写作类似。 我也同意仔细检查I / O是否真的是瓶颈的建议。 由于这样的错误,我第一次看到那篇文章。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM