(道歉有些冗长的介绍)
在此期间,prefaults整个大文件(> 400MB)到缓冲区缓存后加快了实际运行的应用程序的开发,我测试是否每次读4MB仍然有超过一次读取只有1MB块任何明显的好处.令人惊讶的是,较小的请求实际上变得更快.这似乎违反直觉,所以我进行了更广泛的测试.
缓冲区缓存在运行测试之前被清除(只是为了笑,我也在缓冲区中运行了一个文件.无论请求大小如何,缓冲区缓存都能提供高达2GB/s的速度,但令人惊讶的是+/- 30%随机方差).
使用的所有读取都与相同的目标缓冲区重叠ReadFile(使用FILE_FLAG_OVERLAPPED和不 使用句柄打开FILE_FLAG_NO_BUFFERING).使用的硬盘有点老,但功能齐全,NTFS的簇大小为8kB.初始运行后磁盘进行了碎片整理(6个碎片与未碎片,零差异).为了更好的数字,我也使用了更大的文件,下面的数字是读取1GB.
结果真的令人惊讶:
4MB x 256 : 5ms per request, completion 25.8s @ ~40 MB/s
1MB x 1024 : 11.7ms per request, completion 23.3s @ ~43 MB/s
32kB x 32768 : 12.6ms per request, completion 15.5s @ ~66 MB/s
16kB x 65536 : 12.8ms per request, completion 13.5s @ ~75 MB/s
Run Code Online (Sandbox Code Playgroud)
因此,这表明提交数千个请求两个簇的长度实际上比提交几百个大的连续读取更好.提交时间(ReadFile返回之前的时间)确实随着请求数量的增加而上升,但异步完成时间几乎减半.
在每种情况下,内核CPU时间大约为5-6%(在四核上,所以应该说20-30%),而异步读取正在完成,这是一个惊人的CPU数量 - 显然操作系统做了一些非也是无比的忙碌等待.在2.6 GHz时,30%的CPU持续25秒,这是"无所事事"的相当多的周期.
知道如何解释这个吗?也许这里有人对Windows重叠IO的内部工作有更深入的了解?或者,您是否可以使用ReadFile读取兆字节的数据?
我可以看到IO调度程序如何通过最小化搜索来优化多个请求,尤其是当请求是随机访问时(它们不是!).我还可以看到,在NCQ中给出一些请求,硬盘如何能够执行类似的优化.
然而,我们谈论的是荒谬的一些荒谬的小要求 - 尽管如此,它们的表现仍然超过2倍的合理要求.
旁注:明显的赢家是内存映射.我几乎倾向于添加"毫不奇怪",因为我是内存映射的忠实粉丝,但在这种情况下,它实际上让我感到惊讶,因为"请求"甚至更小,操作系统应该更不能预测和安排IO.我最初没有测试内存映射,因为它似乎反直觉,甚至可以远程竞争.那么多你的直觉,嘿.
在不同偏移处重复映射/取消映射视图几乎为零时间.使用16MB视图并使用简单的for()循环对每个页面进行错误操作,每页读取一个字节,在9.2秒内完成@~111 …