Издательский дом ООО "Гейм Лэнд"ЖУРНАЛ ХАКЕР 116, АВГУСТ 2008 г.

Бескомпромиссный тюнинг NTFS

Крис Касперски

Хакер, номер #116, стр. 116-130-1

Скрытые рычаги управления файловой системой семейства ОС Windows NT

NTFS – возможно, самая сложная файловая система из всех, когда-либо разработанных человечеством. Ее разработчики в стремлении объять необъятное скрестили передовые технологии в области баз данных, поиска, сжатия и шифрования информации. Вот только забыли прикрутить рычаги управления…

Полет на пепелаце с жестким диском

Извечный вопрос, переросший в вооруженный конфликт, — бить или не бить? В смысле, на разделы. Стучать молотком по винчестеру может только вандал, а таковых среди нас нет, но у всех есть свои аргументы и контраргументы. WinNT – это не xBSD, групп цилиндров здесь нет.

Что такое группа цилиндров? Чтобы сократить перемещение головок и снизить фрагментацию, файловые системы xBSD (и некоторых других UNIX-клонов) бьют раздел на несколько зон. У каждой из них свои служебные структуры данных и в грубом приближении зоны представляют собой полноценный дисковый том за тем исключением, что расположение одного файла в двух (и более) зонах все-таки возможно, чего не скажешь о логических разделах (имея по 100 Гб на дисках С и D, 200-гиговый файл никак не запишешь…).

Зональное деление приносит огромную пользу, повышая отказоустойчивость диска за счет «размазывания» критической служебной информации по его поверхности и локализуя связанные с ней файлы в одном месте. Теперь возьмем неразбитый диск с NTFS… MFT (служебный файл, хранящий имена, атрибуты и схему размещения всех файлов на диске) находится в начале раздела, индексы, ответственные за содержимое каталогов, – в конце. Ну а сами файлы разбрелись по обширной территории — вот и лови их. Примечание: компактные файлы, называемые «резидентными», хранятся непосредственно в MFT, что теоретически уменьшает время доступа, и подобная техника используется, в частности, в ReiserFS, однако, как показала практика, вместо ожидаемого увеличения производительности мы имеем тормоза, причем в NTFS эта фича легальными путями никак не отключаема. Магнитным головкам приходится совершать огромное количество перемещений на большие дистанции, а на большие дистанции головка перемещается совсем не так, как на короткие — сервопривод получает мощный импульс и оказывается… где-то в окрестностях обозначенной зоны. После чего серия коротких перемещений (метод вилки) приводит его к искомому сектору. Это не только усиливает износ механики, но и увеличивает время поиска информации.

Как достичь предельной скорости? Нужно разбить диск на несколько разделов, размер которых для дисков с одной физической головой лучше выбирать в пределах 30 Гб. Соответственно, для диска с двумя головками эта цифра составит 60 Гб и т.д. Количество головок можно узнать при помощи различных диагностических программ или – скачав hdd datasheet от фирмы-производителя. Показаниям BIOS доверять нельзя, поскольку жесткий диск на логическом интерфейсном уровне работает с виртуальными головками, количество которых запросто может достигать 64 штук.

После разбивки – перед форматированием диска – следует определить два важнейших параметра: размер кластера и размер MFT-файла. От правильности выбора во многом зависят производительность и срок службы жесткого диска в целом. Размер кластера выбирается штатным образом в любой утилите форматирования — как консольной, так и графической. Размер кластера всегда кратен размеру сектора (512 байт для всех жестких дисков) и по умолчанию составляет 4 Кб (8 секторов). Короткие кластеры экономят дисковое пространство (особенно при работе с большим количеством файлов), предотвращая «хвостование» информации на концах. С другой стороны, чем длиннее кластер, тем ниже фрагментация, а, следовательно, жесткий диск может дольше работать без дефрагментации. Но нужно помнить, что при большем размере кластера отключается встроенная в файловую систему возможность сжатия индивидуальных файлов, а также перестает работать стандартный API дефрагментации.

По умолчанию при форматировании диска операционная система резервирует под MFT-файл 10% от неформатной емкости тома, высвобождая эту область только при заполнении диска более чем на 90%. Именно поэтому считается, что MFT-файл не подвержен фрагментации. Но если на диске хранится большое количество мелких файлов, то размера MFT в какой-то момент начинает не хватать. Он растет, подхватывая фрагментированные куски свободного пространства. То же самое происходит и при заполнении диска более чем на 90% — остаток зарезервированной области усекается, выделяясь в общий пул свободного пространства. Обратно в MFT уже не возвращается, и потому его фрагментация неизбежна, если, конечно, не позаботиться о решении проблемы заранее. Например, можно просто создать в цикле огромное количество файлов нулевой длины. Точное количество зависит от размера структуры FILE_RECORD в MFT (она переменчива), но для наших целей вполне подойдет и упрощенная формула: N_FILEZ = DISK_SIZE/2, где размер тома выражен в килобайтах. Удаляем все файлы кроме двух-трех, созданных последними. Как нетрудно догадаться, они будут располагаться в самом конце MFT, жестко фиксируя его нижний размер (что предотвратит высвобождение MFT-области в общий пул). Более точная формула отталкивается не от размера тома, а от количества файлов (и каталогов), которые предполагается создавать на данном томе. Это с учетом того, что при удалении файла соответствующая ему FILE_RECORD высвобождается не сразу, и при создании нового файла из MFT выделяется пространство для новой FILE_RECORD.

Многие руководства упоминают якобы недокументированный (на самом деле, уже давно как документированный самой Microsoft) ключ реестра HKEY_LOCAL_MACHINESystemCurrentControlSetControlFileSystem с хитрым параметром NtfsMftZoneReservation, который управляет размером резервируемой MFT-зоны для вновь форматируемых дисков. По умолчанию он равен 1 — резервировать минимум пространства. «Минимум» — это 10%. Однако поведение системы можно изменить, выбрав значение 2, 3 или даже 4 (максимальный резервируемый объем). Сколько именно Microsoft понимает под «максимумом», она оглашать отказывается, и о точных значениях ключей 2, 3 и 4 остается только гадать. Я ковырнул драйвер NTFS.SYS дизассемблером, но резервируемый объем непостоянен. Он разнится от версии к версии. Более того, даже если мы зарезервируем, например, 50% диска — все равно это не решит проблемы фрагментации NTFS, поскольку по мере заполнения диска зарезервированное пространство автоматически высвобождается. А вот метод создания большого количества мелких файлов с их последующим удалением работает «на ура». Так что, возьмем его себе на вооружение.

Ключ NtfsMemoryUsage – на редкость полезная штука. По умолчанию выставленный в 1 он ограничивает аппетит NTFS в плане использования памяти, устанавливая жесткие лимиты на размер дискового кэша и количество информации, хранимой для открытых файлов. Для рабочих станций — все ОК, но для сервера, оснащенного большим количеством RAM и чувствительного к быстродействию дисковой подсистемы, значение лучше установить в 2. И затем перезагрузиться, чтобы изменения вступили в силу.

Гравицапа для NTFS

Наконец, разбитый на разделы и отформатированный диск лежит перед нами и, тихо жужжа, начинает заполняться файлами. Только что-то он тормозит, да и красный светодиод мигает, даже когда к приводу нет видимых обращений. Зато есть масса невидимых. Для ускорения доступа к данным Microsoft реализовала систему индексации, задействованную по умолчанию и отключаемую через свойства диска. Вызываем из проводника контекстное меню, далее – Properties, вкладка «General», а там – галочка напротив пункта «Allow Indexing Service to index the disk for fast file searching». Сбрасываем ее немедленно! Все равно никакого быстрого поиска мы не получим, зато приобретем тормоза и повышенный износ дисков.

Вместе с индексацией рекомендуется отключить и журналирование. Как известно, NTFS – журналируемая файловая система, что выдается Microsoft за достоинство, хотя это, скорее, недостаток. Журнал не только занимает место и отнимает драгоценное время, замедляя интенсивные дисковые операции, но и в некоторых случаях приводит к полному краху. В коде, связанном с поддержкой журнала, за историю существования NTFS в релизных версиях WinNT/200x было обнаружено, по меньшей мере, три ошибки, приводящие к BSOD при попытке монтирования NTFS тома. Знающие люди использовали загрузочные диски с Linux, поддерживающие NTFS на базовом уровне (то есть, без журналирования), перегоняя все ценные файлы по сети на соседний компьютер или уничтожая журнал в дисковых редакторах/системных утилитах.

Зачем лишние мучения? Берем утилиту fsutil.exe, входящую в штатный комплект поставки Win2k3, и удаляем журнал, запрещая журналирование для диска X: «fsutil usn deletejournal /D X:». Если мы потом захотим вернуть журнал на место, нет проблем: «fsutil usn createjournal m=1000 a=100 X:».

Вместе с журналированием можно отключить и шифрование, обратившись к уже известному нам ключу реестра HTLMSystemCurrentControlSetControlFileSystem и создав параметр NtfsDisableEncryption типа DWORD, установленный в 1. После перезагрузки системы попытка применения атрибута шифрования к файлам и папкам будет выдавать ошибку, что очень хорошо! Почему? Потому что система шифрования в Win2k3 реализована далеко не лучшим образом; без ключей все зашифрованные данные становятся недоступными. Пользователи, не разбирающиеся в администрировании, но уже освоившие мышь, зачастую шифруют все данные, к которым только имеют доступ! При переустановке сервера «энтузиазм» пользователей выплывает наружу, и хотя данные за разумное время можно расшифровать без ключа, проблему предпочтительно пресечь на корню. Кроме того, шифрование негативно сказывается на быстродействии NTFS.

Параметр NtfsDisableCompression того же самого ключа реестра запрещает применение атрибута сжатия для всех файлов. Чем плохо сжатие? А тем, что сжатые файлы труднее восстанавливать в случае краха диска. Их не поддерживают утилиты автоматизированного восстановления (мне неизвестно ни одной, которая бы поддерживала), их не понимают драйвера для NTFS от Linux, а спецы по восстановлению в этом случае увеличивают сумму контракта. К тому же, NTFS жмет плохо, – сжатые файлы тормозят и жрут память.

Секреты эффективного использования NTFS

В отличие от FAT32, где все свалено в кучу, NTFS использует двоичную организацию файловых каталогов, что (теоретически) должно увеличить производительность, сократив время поиска файла в каталоге. Однако неудачная реализация сгубила эту идею, продемонстрировав прямо противоположный эффект. NTFS крайне плохо справляется с каталогами, содержащими десятки и сотни тысяч файлов. Особенно, если кроме операций открытия (фактически, сводящихся к поиску заданного имени в дереве), мы занимаемся созданием новых файлов/удалением старых, вынуждая NTFS перестраивать кучу служебных структур, живописно разбросанных по диску.

Увы… это фундаментальная проблема NTFS, не имеющая универсальных решений. Когда это возможно, следует уменьшать количество файлов в каталоге, разбрасывая их по подкаталогам. Причем именовать файлы желательно так, чтобы на первые буквы имени приходилось максимум различий – file_1, file_2, file_3… будет тормозить сильнее, чем 1_file, 2_file, 3_file. Вроде бы мелочь, а разница в скорости колоссальна!

Каталоги, содержащие массу мелких файлов, к которым постоянно происходит обращение, имеет смысл размещать на виртуальных дисках, не жалея оперативной памяти. Полученное ускорение покроет все расходы с головой.

Другая проблема NTFS связана с фрагментацией. Несмотря на то, что изначально она разрабатывалась как файловая система, практически свободная от фрагментации, стратегия «правильного» выделения дискового пространства навечно осталась в стадии разработки. Текущие версии NTFS фрагментируются приблизительно так же, как и FAT, что ведет к неуклонной деградации производительности.

Штатный дефрагментатор, представляющий собой сильно урезанный вариант коммерческого «O&O Defrag», не умеет дефрагментировать открытые файлы, к которым, в первую очередь, относятся: файл подкачки, реестр, куча системных файлов и т.д. А потому с каждым днем сервер тормозит все сильнее и сильнее. Единственный способ вернуть былую производительность – обзавестись полной версией O&O Defrag или любого другого достойного дефрагментатора, поддерживающего дефрагментацию в boot-time, то есть на стадии загрузки. Boot-программы исполняются в монопольном режиме задолго до наступления многозадачности, и потому риск, что кто-то обратится к дефрагментируемым данным в момент их перемещения, здесь полностью исключен.

Разреженные файлы на службе прогресса

NTFS поддерживает sparse-файлы, выделяя дисковое пространство только актуальным данным и подсовывая нули тем, которые еще не были проинициализированы. Это сокращает размер файла – в десятки, сотни и даже тысячи раз! Чтобы назначить файлу атрибут «разреженного», следует воспользоваться утилитой fsutil из штатного комплекта поставки Win2k3, вызвав ее с ключом «sparse setflag»: «fsutil sparse setflag X:nezumi.txt». После того, как файл создан и заполнен данными, из него можно выбить весь «пух», дав команду «fsutil sparse setrange FileName BeginningOffset Length», где BeginningOffset — начальное смещение «разреженной» области (обычно равное нулю), а Length – ее длина (как правило, равная размеру файла, округленного до размера кластеров).

INFO

Старайся не располагать файл подкачки на зеркальном RAID массиве – это снизит скорость работы.

WARNING

Поскольку версий NTFS существует намного больше одной, то при использовании дисковых утилит от сторонних разработчиков требуется проверить их на совместимость с нашей версией. Установи ее (со всеми обновлениями) на виртуальную машину/отдельный жесткий диск. Но даже если тест прошел «на ура», настоятельно рекомендую освежить резервные копии, особенно когда дисковая утилита на живой машине запускается в первый раз.

WWW

На technet2.microsoft.com можно найти интересные статьи, посвященные работе с NTFS.

Содержание
ttfb: 5.0239562988281 ms