windows 如何让 CreateFile 尽可能快

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7430959/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 18:05:13  来源:igfitidea点击:

How to make CreateFile as fast as possible

windowsperformancewinapifile-ioio

提问by Macker

I need to read the contents of several thousands of small files at startup. On linux, just using fopen and reading is very fast. On Windows, this happens very slowly.

我需要在启动时读取数千个小文件的内容。在linux上,只使用fopen,读取速度非常快。在 Windows 上,这发生得非常缓慢。

I have switched to using Overlapped I/O (Asynchronous I/O) using ReadFileEx, where Windows does a callback when data is ready to read.

我已经切换到使用 ReadFileEx 使用重叠 I/O(异步 I/O),当数据准备好读取时,Windows 会执行回调。

However, the actual thousands of calls to CreateFile itself are still a bottleneck. Note that I supply my own buffers, turn on the NO_BUFFERING flag, give the SERIAL hint, etc. However, the calls to CreateFile take several 10s of seconds, whereas on linux everything is done much faster.

然而,实际上对 CreateFile 本身的数千次调用仍然是一个瓶颈。请注意,我提供了自己的缓冲区、打开 NO_BUFFERING 标志、提供 SERIAL 提示等。然而,对 CreateFile 的调用需要几十秒,而在 linux 上,一切都完成得更快。

Is there anything that can be done to get these files ready for reading more quickly?

有什么办法可以让这些文件准备好以更快地阅读吗?

The call to CreateFile is:

对 CreateFile 的调用是:

            hFile = CreateFile(szFullFileName,
                GENERIC_READ,
                FILE_SHARE_READ | FILE_SHARE_WRITE,
                NULL,
                OPEN_EXISTING,
                FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED | FILE_FLAG_NO_BUFFERING | FILE_FLAG_SEQUENTIAL_SCAN,
                NULL);

回答by Chris Smith

CreateFilein kernel32.dllhas some extra overhead compared to the kernel syscall NtCreateFilein ntdll.dll. This is the real function that CreateFilecalls to ask the kernel to open the file. If you need to open a large number of files, NtOpenFilewill be more efficient by avoiding the special cases and path translation that Win32 has-- things that wouldn't apply to a bunch of files in a directory anyway.

CreateFilekernel32.dll与内核系统调用NtCreateFilein相比,in有一些额外的开销ntdll.dll。这是CreateFile调用请求内核打开文件的真正函数。如果您需要打开大量文件,NtOpenFile通过避免 Win32 具有的特殊情况和路径转换会更有效 - 无论如何都不适用于目录中的一堆文件的东西。

NTSYSAPI NTSTATUS NTAPI NtOpenFile(OUT HANDLE *FileHandle, IN ACCESS_MASK DesiredAccess, IN OBJECT_ATTRIBUTES *ObjectAttributes, OUT IO_STATUS_BLOCK *IoStatusBlock, IN ULONG ShareAccess, IN ULONG OpenOptions);

HANDLE Handle;
OBJECT_ATTRIBUTES Oa = {0};
UNICODE_STRING Name_U;
IO_STATUS_BLOCK IoSb;

RtlInitUnicodeString(&Name_U, Name);

Oa.Length = sizeof Oa;
Oa.ObjectName = &Name_U;
Oa.Attributes = CaseInsensitive ? OBJ_CASE_INSENSITIVE : 0;
Oa.RootDirectory = ParentDirectoryHandle;

Status = NtOpenFile(&Handle, FILE_READ_DATA, &Oa, &IoSb, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, FILE_SEQUENTIAL_ONLY);

Main downside: this API is not supported by Microsoft for use in user mode. That said, the equivalent function is documented for kernel mode useand hasn't changed since the first release of Windows NT in 1993.

主要缺点:Microsoft 不支持在用户模式下使用此 API。也就是说,等效函数被记录用于内核模式,并且自 1993 年首次发布 Windows NT 以来没有改变。

NtOpenFilealso allows you to open a file relative to an existing directory handle (ParentDirectoryHandle in the example) which should cut down on some of the filesystem overhead in locating the directory.

NtOpenFile还允许您打开相对于现有目录句柄(示例中的 ParentDirectoryHandle)的文件,这应该会减少定位目录时的一些文件系统开销。

In the end, NTFS may just be too slow in handling directories with large numbers of files as Carey Gregory said.

最后,正如 Carey Gregory 所说,NTFS 在处理包含大量文件的目录时可能太慢了。

回答by GReg

Try paging in the MFT efficiently before issuing the Create file. This can be done by issuing FSCTL_ENUM_USN_DATA.

在发出创建文件之前,尝试在 MFT 中有效地分页。这可以通过发出 FSCTL_ENUM_USN_DATA 来完成。