Почему для записи большого файла на диск fsutil.exe требуется меньше времени, чем программно?
Этот вопрос соответствует этой теме: создание огромного фиктивного файла за считанные секунды в C#
Я только что проверил fsutil.exe в xp/vista/seven, чтобы записать огромное количество фиктивных данных на диск хранения, и запись такого большого файла занимает меньше времени по сравнению с программным способом.
Когда я пытаюсь сделать то же самое с помощью.net, это займет значительно больше времени, чем fsutil.exe.
примечание: я знаю, что.net не использует нативный код, потому что я только что проверил эту проблему с нативным 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, которая имеет такую скорость записи?
4 ответа
Я не знаю точно, что делает fsutil, но я знаю два способа написания большого файла, который быстрее, чем то, что вы делали выше (или поиск нужной длины и запись нуля, который имеет то же самое результат).
Проблема с этими подходами состоит в том, что они заполняют файл нулем во время записи.
Вы можете избежать заполнения нуля одним из следующих способов:
- Создание разреженного файла. Размер отмечен там, где вы хотите, но на самом деле данные не существуют на диске, пока вы не напишите их. Все чтения неписанных областей будут возвращать нули.
- Использование функции SetFileValidData для установки правильной длины данных без обнуления файла в первую очередь. Однако из-за потенциальных проблем безопасности эта команда требует повышенных разрешений.
Я согласен с последним комментарием. Я экспериментировал с драйвером минифильтра и захватывал IRP IRP_MJ_WRITE в режиме обратного вызова. Когда я создаю или записываю файл из строки 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.