Как сделать CreateFile максимально быстрым - PullRequest
6 голосов
/ 15 сентября 2011

Мне нужно прочитать содержимое нескольких тысяч маленьких файлов при запуске.В Linux просто использование fopen и чтение очень быстро.В Windows это происходит очень медленно.

Я перешел на использование перекрывающегося ввода-вывода (асинхронного ввода-вывода) с использованием ReadFileEx, где Windows выполняет обратный вызов, когда данные готовы для чтения.Однако фактические тысячи вызовов самого 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);

Ответы [ 2 ]

11 голосов
/ 10 октября 2011

CreateFile в kernel32.dll имеет некоторые дополнительные издержки по сравнению с системным вызовом ядра NtCreateFile в 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);

Основной недостаток: этот API не поддерживается Microsoft для использования в пользовательском режиме.При этом эквивалентная функция задокументирована для использования в режиме ядра и не изменилась с момента первого выпуска Windows NT в 1993 году.

NtOpenFile также позволяет открывать файл относительнок существующему дескриптору каталога (ParentDirectoryHandle в примере), который должен сократить некоторые издержки файловой системы при поиске каталога.

В конце концов, NTFS может быть слишком медленной в обработке каталогов с большим количеством файловкак сказал Кэри Грегори.

0 голосов
/ 13 февраля 2012

Попробуйте выполнить эффективную подкачку в MFT перед выдачей файла Create.Это можно сделать, выдав FSCTL_ENUM_USN_DATA.

...