почему fsutil.exe для записи огромного файла на диск требуется меньше времени, чем программно?
Вопрос
этот вопрос соответствует этой теме:создание огромного фиктивного файла за считанные секунды на c#
Я только что проверил fsutil.exe в xp / vista / seven для записи огромного количества фиктивных данных на диск хранения требуется меньше времени для записи такого большого файла по сравнению с программным способом.
Когда я пытаюсь сделать то же самое с помощью .net, это займет значительно больше времени, чем fsutil.exe.
примечание:Я знаю, что .net не использует машинный код, из-за этого я просто проверил эту проблему с помощью native api, например, следующим образом:
long int size = DiskFree('L' - 64);
const char* full = "fulldisk.dsk";
__try{
Application->ProcessMessages();
HANDLE hf = CreateFile(full,
GENERIC_WRITE,
0,
0,
CREATE_ALWAYS,
0,
0);
SetFilePointer(hf, size, 0, FILE_BEGIN);
SetEndOfFile(hf);
CloseHandle(hf);
}__finally{
ShowMessage("Finished");
exit(0);
и ответ был таким же равным, как и результаты .net.
но с помощью fsutil.exe это занимает меньше времени, чем указано выше, или подходы .net говорят, что это в 2 раза быстрее
пример :для записи 400 мб с помощью .net это займет ~ 40 секунд столько же с помощью fsutil.exe займет около 20 секунд или меньше.
есть ли этому какое-нибудь объяснение?или какая функция fsutil.exe использует ли то, что имеет такое значение, скорость записи?
Решение
Я не знаю точно, что делает fsutil, но я знаю о двух способах записи большого файла, которые быстрее, чем то, что вы сделали выше (или поиск нужной длины и запись нуля, что дает тот же результат).
Проблема с этими подходами заключается в том, что они обнуляют файл во время выполнения записи.
Вы можете избежать заполнения нулем либо:
- Создание разреженного файла.Размер указан там, где вы хотите, но данные фактически не существуют на диске, пока вы их не запишете.Все чтения из неписаных областей вернут нули.
- Используя SetFileValidData Установить значение файла функция для установки допустимой длины данных без предварительного обнуления файла.Однако из-за потенциальных проблем с безопасностью для этой команды требуются повышенные разрешения.
Другие советы
Я согласен с последним комментарием.Я экспериментировал с драйвером минифильтра и записывал IRP_MJ_WRITE IRPS в обратном вызове.Когда я создаю или записываю в файл из cmd-строки или приложения win32, я вижу, что записи прекращаются.Но когда я создал файл с помощью команды "fsutil file createnew ...", я не вижу никаких записей.Я вижу такое поведение на win2k8 r2 на томе NTFS.И я не думаю (хотя и не уверен на 100%), что это разреженный файл.Вероятно, это настройка свойств размера в MFT без выделения какого-либо кластера.fsutil проверяет доступное свободное место, поэтому, если размер файла больше, чем свободное место на диске, вы получите сообщение об ошибке 1.
Я также запустил программу, определяющую FSCTL_GET_RETRIEVAL_POINTERS для файла, и я получил один экстент для всего размера файла.Но я считаю, что он получает все данные
Это то, что могло бы быть
- Написано на ассемблере (необработанная скорость ослепления)
- Собственный код на C / C ++ для этого
- Возможно, недокументированный системный вызов для этого или какой-то трюк, который нигде не задокументирован.
Вышеприведенные три пункта могут иметь огромное значение - если подумать, при загрузке .NET-кода среда выполнения приводит к сбоям (Ок, фактор времени не будет заметен, если у вас невероятно быстрая машина - на скромном pentium это было бы заметно при медленной загрузке).
Более чем вероятно, что это могло быть написано либо на C / C ++.Вас может удивить, если она была написана на ассемблере.
Вы можете проверить это сами - посмотрите на размер исполняемого файла и сравните его с исполняемым файлом .NET.Вы можете возразить, что файл сжат, в чем я сомневаюсь, и поэтому склонен исключить это, Microsoft не зашла бы так далеко, я считаю, что сжатие исполняемых файлов - это бизнес.
Надеюсь, это ответ на твой вопрос, С наилучшими пожеланиями, Том.
fsutil работает быстро только в NTFS и exFAT, но не в FAT32, FAT16 Это потому, что некоторые файловые системы имеют ограничение на "инициализированный размер" и, таким образом, поддерживают быструю инициализацию файлов.Это просто резервирует кластеры, но не обнуляет их, потому что в файловой системе отмечается, что в файл не было записано никаких данных, и все допустимые чтения будут возвращать буферы, заполненные 00.