我可以精确计时重叠的 ReadFileEx 操作吗?

Posted

技术标签:

【中文标题】我可以精确计时重叠的 ReadFileEx 操作吗?【英文标题】:Can I precisely time overlapped ReadFileEx operations? 【发布时间】:2011-06-14 09:29:38 【问题描述】:

我正在使用ReadFileEx(使用 CreateFile 和 FILE_FLAG_NO_BUFFERING 标志打开)从文件中读取扇区对齐的块,记录调用前的开始时间和完成例程中的结束时间(时间来自 QueryPerformanceCounter)。

无论整个文件的大小如何,我的块读取的大小都是恒定的。块偏移按顺序排列,因此 ReadFileEx 总是在文件中读取比最后一个点更远的点。我注意到一些奇怪的行为,例如较小的文件记录的块读取时间比较大的文件要快得多。

在这种情况下,较大文件的大小是较小文件的两倍 - 我不应该期望这在原始数据读取级别上很重要,因为无论如何我正在读取相同大小的块。我看到的是较小的文件报告读取速度为 160mb/s,而较大的文件报告读取速度为 110mb/s。

我仍在努力假设是我的代码中的其他东西导致了问题。我还希望读取操作在 ReadFileEx + GetLastError 返回 ERROR_IO_PENDING 后的某个操作系统定义点开始。

编辑:我的计时不准确已通过调整我的读取线程得到进一步确认,因此它有更多时间在警报状态下等待完成处理程序通知。这提高了报告的读取速度,表明我的部分问题是完成处理程序在读取完成后没有立即被调用(因此我的结束时间比它应该的晚)。但是,这样做会按比例提高较大和较小文件的报告速度。

TL;DR 我的问题是,我可以测量读取操作的实际时间,而不是调用 ReadFileEx 之间的时间(可能不会直接开始读取离开)和完成例程?

【问题讨论】:

只是为了澄清一下,您是在不等待完成的情况下拨打多个ReadFileEx,还是每次完成都拨打一个ReadFileEx?据我所知,没有简单的方法来计算实际阅读的时间。 @dauphic 我正在进行多个 ReadFileEx 调用,每个调用都在读取完成后的某个时间点调用完成处理程序。 对此我不是 100%,但我相信操作系统可能会决定同时执行多个读取。这可能会损坏对大文件的读取。我的经验是,重叠读取仅用于与处理最后一次读取并行执行下一次读取,而不是对多次读取进行排队。 @dauphic 你能解释一下它会如何损坏读取吗? 对不起,我的意思是读取性能。根据缓存的不同,磁头最终可能会跳来跳去,以服务并发读取请求。 【参考方案1】:

TL;DR 我的问题是,我可以测量 读操作的实际时间, 而不是通话之间的时间 ReadFileEx(它可能不会启动 立即阅读)和完成 例行公事?

可能不是来自用户模式代码。

您无法控制的变量太多。您不知道可能需要什么搜索(例如,一个文件可能是碎片化的,另一个可能不是)。文件映射(文件段到磁盘块)可能已经被缓存,也可能没有被缓存。即使没有读取缓冲区,仍然存​​在集群、驱动器上重新排序、驱动器上缓存等。通过异步操作,您还可以使用调度程序。

使用驱动器,您可以进行一些精确的测量,但您仍然需要进行大量实验并计算平均值以获得统计结果,以排除驱动器内部发生的所有奇怪事情(重试、重新排序、使用备件、板载缓存、区域位记录、热重新校准等)。

【讨论】:

以上是关于我可以精确计时重叠的 ReadFileEx 操作吗?的主要内容,如果未能解决你的问题,请参考以下文章

C# .NET/Mono 中精确可靠的步进计时

C#下利用高精度计时器进行计时操作

网络音频 api 计时是不是比 setTimeout 更精确

C++中如何精确计时

c#的timer控件计时不够准确,有啥办法可以替代吗,我需要10ms左右的精度,但是timer很不准确

精确点击重叠 div