Почему для записи большого файла на диск 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, но я знаю два способа написания большого файла, который быстрее, чем то, что вы делали выше (или поиск нужной длины и запись нуля, который имеет то же самое результат).

Проблема с этими подходами состоит в том, что они заполняют файл нулем во время записи.

Вы можете избежать заполнения нуля одним из следующих способов:

  1. Создание разреженного файла. Размер отмечен там, где вы хотите, но на самом деле данные не существуют на диске, пока вы не напишите их. Все чтения неписанных областей будут возвращать нули.
  2. Использование функции 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.

Другие вопросы по тегам