How to make CreateFile as fast as possible

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

I switched to using Overlapped I / O (asynchronous I / O) with ReadFileEx, where Windows calls back when the data is ready to read.

However, the actual thousands of calls to CreateFile itself are still the bottleneck. Note that I supply my own buffers, enable the NO_BUFFERING flag, give the SERIAL hint, etc. However, CreateFile calls take several tens of seconds, while on Linux everything is done much faster.

Is there anything that can be done to make these files ready to read faster?

CreateFile call:

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); 
+5
source share
2 answers

CreateFile in kernel32.dll has some additional overhead compared to the syscall NtCreateFile in ntdll.dll . This is a real function that calls CreateFile to ask the kernel to open the file. If you need to open a large number of files, NtOpenFile will be more efficient, avoiding special cases and transforming the path that Win32 has - things that in any case will not apply to a bunch of files in a directory.

 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 disadvantage: this API is not supported by Microsoft for use in user mode. However, the equivalent function is documented to use kernel mode and has not changed since the first version of Windows NT in 1993.

NtOpenFile also allows you to open a file relative to an existing directory descriptor (ParentDirectoryHandle in the example), which should reduce some of the file system overhead when searching for a directory.

After all, NTFS can be too slow when processing directories with lots of files, as Carey Gregory said.

+10
source

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

0
source

Source: https://habr.com/ru/post/980718/


All Articles