如何使CreateFile尽可能快

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

我已经使用ReadFileEx切换到使用重叠I / O(asynchronousI / O),其中Windows在数据准备好读取时执行callback。

然而,实际上成千上万的CreateFile调用本身仍然是一个瓶颈。 请注意,我提供了自己的缓冲区,打开NO_BUFFERING标志,提供SERIAL提示等。但是,对CreateFile的调用需要几十秒的时间,而在Linux上,所有操作都要快得多。

有什么可以做的,让这些文件准备好更快地阅读?

对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); 

CreateFile中的CreateFile相比, ntdll.dll的内核系统调用NtCreateFile有一些额外的开销。 这是CreateFile调用来请求内核打开文件的真实函数。 如果你需要打开大量的文件, NtOpenFile会避免Win32的特殊情况和路径转换 – 这些东西不会适用于目录中的一堆文件, NtOpenFile提高效率。

 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); 

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

NtOpenFile还允许你打开一个相对于现有目录句柄的文件(在这个例子中是ParentDirectoryHandle),这样可以减少查找目录的一些文件系统开销。

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

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