windows - 如何从磁盘获得良好的并发读取性能

标签 windows multithreading file-io

我想提出一个问题,然后用我自己的答案跟进,但也想看看其他人有什么答案。

我们有两个大文件,我们想从两个独立的线程中同时读取它们。一个线程将顺序读取文件 A,而另一个线程将顺序读取文件 B。线程之间没有锁定或通信,它们都以尽可能快的速度顺序读取,并且都立即丢弃它们读取的数据。

我们在 Windows 上使用此设置的体验非常差。两个线程的组合吞吐量约为 2-3 MiB/秒。该驱动器似乎大部分时间都在两个文件之间来回搜索,大概每次搜索后读取的内容很少。

如果我们禁用其中一个线程并暂时查看单个线程的性能,那么我们将获得更好的带宽(对于这台机器而言约为 45 MiB/秒)。很明显,糟糕的双线程性能是操作系统磁盘调度程序的产物。

我们可以做些什么来提高并发线程读取性能吗?也许可以通过使用不同的 API 或以某种方式调整 OS 磁盘调度程序参数。

一些细节:

在具有 2GiB RAM 的机器上,每个文件的大小约为 2GiB。出于这个问题的目的,我们认为它们不会被缓存和完美碎片整理。我们已使用碎片整理工具并重新启动以确保情况如此。

我们没有使用特殊的 API 来读取这些文件。该行为可跨各种沼泽标准 API 重复,例如 Win32 的 CreateFile、C 的 fopen、C++ 的 std::ifstream、Java 的 FileInputStream 等。

每个线程都在一个循环中旋转,调用读取函数。我们改变了每次迭代从 API 请求的字节数,范围从 1KiB 到 128MiB。改变这个没有效果,所以很明显操作系统在每次磁盘搜索后物理读取的数量不受这个数字的影响。这正是我们所期望的。

单线程和双线程性能之间的显着差异在 Windows 2000、Windows XP(32 位和 64 位)、Windows Server 2003 以及使用和不使用硬件 RAID5 中重复出现。

最佳答案

问题似乎出在 Windows I/O 调度策略中。据我查到here操作系统有很多方法。安排磁盘请求。虽然 Linux 和其他系统可以在不同的策略之间进行选择,但在 Vista Windows 之前,Windows 被锁定在一个单一的策略中:一个 FIFO 队列,所有请求都被分成 64 KB block 。我相信此策略是导致您遇到的问题的原因:调度程序将混合来自两个线程的请求,导致磁盘不同区域之间的连续搜索。
现在,好消息是根据 herehere , Vista 引入了更智能的磁盘调度程序,您可以在其中设置请求的优先级,还可以为您的进程分配最小带宽。
坏消息是我发现无法在以前版本的 Windows 中更改磁盘策略或缓冲区大小。此外,即使提高进程的磁盘 I/O 优先级会提高相对于其他进程的性能,您仍然会遇到线程相互竞争的问题。
我可以建议的是通过引入自制的磁盘访问策略来修改您的软件。
例如,您可以在线程 B 中使用这样的策略(类似于线程 A):

if THREAD A is reading from disk then wait for THREAD A to stop reading or wait for X ms
Read for X ms (or Y MB)
Stop reading and check status of thread A again  

您可以使用信号量进行状态检查,也可以使用性能计数器来获取实际磁盘队列的状态。 X 和/或 Y 的值也可以通过检查实际传输速率并缓慢修改它们来自动调整,从而在应用程序在不同机器和/或操作系统上运行时最大化吞吐量。您可能会发现缓存、内存或 RAID 级别会以某种方式影响它们,但通过自动调整,您将始终在每种情况下获得最佳性能。

关于windows - 如何从磁盘获得良好的并发读取性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9191/

相关文章:

c# - 我需要在递归算法期间停止执行

Java 编程 - 为应用程序保存/读取数据的最佳方式

c# - 如何使用 c#` 将 pdf 文件从合法格式调整为字母格式

java - 如何通过 start-stop-daemon 优雅地关闭 Spring Boot 应用程序

linux - 为什么 Linux 不使用纤程而不是抢占式多任务处理?

java - 使用SwingWorker动态加载jTable中的大数据

c++ - 在多线程应用程序中等待变量的最佳方法是什么

windows - 在 Virtualbox 上安装多个 Windows 实例

c++ - 如何使用 C++ 检查 python 版本?

windows - 使用提升的权限复制文件