寻求是否比读取更便宜,并且前瞻性是否会导致顺序访问优化?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了寻求是否比读取更便宜,并且前瞻性是否会导致顺序访问优化?相关的知识,希望对你有一定的参考价值。
考虑一下SetFilePointer
。 MSDN上的文档(也不是docs.microsoft.com
)没有解释正向搜索是否构成顺序访问 - 这对应用程序的IO性能有影响。
例如,如果你将CreateFile
与FILE_FLAG_RANDOM_ACCESS
一起使用,那么与FILE_FLAG_SEQUENTIAL_SCAN
相比,Win32将使用不同的缓冲和缓存策略 - 如果你从头到尾阅读文件,那么你可以期望比使用随机访问选项更好的性能。
但是,假设您正在读取的文件格式并不需要将每个字节(甚至缓冲区页面)读入内存,例如文件头中的标志表示前100个字节 - 或100千字节 - 不包含任何用处数据。调用ReadFile
读取接下来的100个字节(或100千字节 - 或更多?)是否明智?或者调用SetFilePointer( file, 100, NULL, FILE_CURRENT )
跳过这100个字节总是更快?
如果使用SetFilePointer
通常更快,那么random-access vs sequential选项会有所不同吗?我认为向前搜索构成一种随机访问形式,因为你可以寻找超出当前缓存的缓冲区(以及操作系统可能在幕后预装的任何未来缓冲区),但在这种情况下,Windows总是会丢弃缓存的缓冲区并从磁盘重新读取?有没有办法找出可以在不触发缓冲区重新加载的情况下寻找转发的最大数量?
(我会尝试对我的假设进行分析和基准测试,但我手边的所有计算机都有NVMe SSD - 显然在盘片驱动器上的情况会有所不同)。
起初关于SetFilePointer
。
SetFilePointer
内部称ZwSetInformationFile
与FilePositionInformation
。由I / O管理器完整的handled - 甚至没有调用文件系统。所有这一切都是在这个召唤上完成的:来自CurrentByteOffset
的FILE_OBJECT
是set到给定的位置。
所以这个调用绝对独立于文件缓冲和缓存策略。更多 - 这是绝对无意义的召唤,只浪费时间 - 我们总是可以在调用ReadFile
或WriteFile
时设置直接偏移 - 查看OVERLAPPED
Offset
和OffsetHigh
。 SetEndOfFile
?但更好更有效的调用ZwSetInformationFile
与FileEndOfFileInformation
或SetFileInformationByHandle
与FileEndOfFileInfo
(SetEndOfFile
当然内部调用ZwSetInformationFile
与FileEndOfFileInformation
,然后它调用ZwQueryInformationFile
与FilePositionInformation
从CurrentByteOffset
读取FILE_OBJECT
- 所以你只需要做2-3个不必要的额外调用内核以防万一SetEndOfFile
)。当调用SetFilePointer
真的需要时不存在的情况。
所以文件位置 - 只是软件变量(CurrentByteOffset
中的FILE_OBJECT
),它使用主要的I / O管理器 - 文件系统始终获得带有显式偏移的读/写请求 - 在FastIoRead
中,如在参数中或在IO_STACK_LOCATION.Parameters.Read.ByteOffset
中,I / O管理器获得此偏移量或从显式的ByteOffset值到NtReadFile
或CurrentByteOffset
在FILE_OBJECT
中如果ByteOffset不存在(ByteOffset的NULL指针)ReadFile
使用NULL指针为ByteOffset如果为OVERLAPPED
的NULL指针,否则使用指向OVERLAPPED.Offset
的指针
关于问题 - 是否存在感知顺序读取所有字节或只是从所需的偏移读取?
如果我们打开没有缓存的文件(FILE_NO_INTERMEDIATE_BUFFERING
) - 我们别无选择Offset和Length传递给ReadFile
或WriteFile
必须是扇区大小的倍数
在使用缓存的情况下 - 如果在读取实际需要的字节之前读取一些额外的(并且不需要我们的字节),我们无论如何都没有收获。在任何情况下,文件系统都需要从磁盘读取这个字节,如果它还没有读取 - 读取另一个字节不会加速这个过程。
使用FILE_FLAG_SEQUENTIAL_SCAN
缓存管理器从磁盘读取更多扇区而不是需要完整的当前请求和下一次读取顺序偏移 - 将(至少部分地)降低缓存 - 因此从磁盘直接读取的计数(最昂贵的操作)将更少。但是当你需要在特定偏移处读取文件时 - 在此偏移之前的顺序读取字节无论如何都无济于事 - 无论如何都需要读取这个字节
换句话说 - 你无论如何都需要从文件中读取所需的字节(在特定的偏移量) - 如果你在此之前读取另外一些字节 - 这不会提高性能。只会减少
因此,如果您需要在某个偏移处读取文件 - 只需读取此偏移量。而不是使用SetFilePointer
。在OVERLAPPED
上使用显式偏移量
以上是关于寻求是否比读取更便宜,并且前瞻性是否会导致顺序访问优化?的主要内容,如果未能解决你的问题,请参考以下文章