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

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

从磁盘流传输的最有效的.NET API是什么?快速磁盘访问的哪些Win32 API可用(值得/召唤)?

有帮助吗?

解决方案

快速文件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. 如果您的读/写是顺序的,请通过应用适当的策略来帮助缓存管理器 - 提供 随机或顺序can, ,当实例化文件流时
  2. 考虑使用较大的内存缓冲区来存储读取数据
  3. 如果复制许多小文件,则可以首先一次将许多文件读取到存储缓冲区(请参阅2),然后将文件写入磁盘
  4. 如果源流和目标流位于不同的位置(即不在同一硬盘驱动器上,也许是网络上的一个文件,另一个在本地硬盘驱动器上等),则可以使用异步模式来加速,通过使用 开始阅读, ,然后使用 BEGINWRITE, ,在写入数据时,使用BeginRead读取下一个数据块。
  5. 如果您仍然认为性能还不够(但是,从我的测试中,它是平等甚至比内部窗口复制更快的速度),则可以使用 CopyFileex win32函数(但此功能可与文件一起使用,而不是流)。

您是否介绍了您的应用程序以确定磁盘I/O是否是瓶颈?

您正在运行哪种类型的硬件?硬件配置是什么?

在.net中,您可以尝试 System.IO.File 名称空间。

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

一个例子:

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

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

BinaryReader and BinaryWriter with a suitable buffer size are pretty fast. If you are reading into structures, the unsafe approach described in this article will get you reading fast, and writing is similar. I also agree with the suggestion to double-check that I/O is really the bottleneck. I first came across that article due to such a mistake.

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