Pull to refresh

Почему по мере заполнения SSD падает скорость записи в RAID, или зачем нужен TRIM

Reading time 7 min
Views 120K
Эта проблема наиболее актуальна для аппаратных RAID или firmware RAID (таких как Intel RST RAID 1/10/5/6) с непромышленными SSD.

Особенность SSD


SSD пишут и читают данные страницами, записать можно только на очищенные страницы, а очистить страницы можно только большими блоками. Например, у диска размер страницы 8 КБ, в блоке находится 128 страниц, таким образом, размер блока — 1024 КБ (здесь и далее, если не указано иного, КБ и МБ двоичные).

Например, если изменить 40 КБ в одном файле, то на физическом уровне это будет выглядеть так:



На логическом уровне всё выглядит как обычно — данные будут перезаписаны поверх в соответствующих секторах. Как только в блоке 1 останутся исключительно пустые и готовые для очистки страницы, этот блок стирается и становится пустым целиком.

Чтобы скрыть физическую реализацию, диск поддерживает карту соответствия логических и физических номеров страниц (Flash Translation Layer).

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

Чтобы решить это проблему, была добавлена команда ATA TRIM (wiki). Операционная система посылает её диску с указанием секторов, которые могут быть очищены. Аналоги этой команды — SCSI UNMAP и CF ERASE. К сожалению, в некоторых случаях нет возможности послать её диску:
— если диск находится в RAID с аппаратным контроллером (LSI, Adaptec и т. п.),
— если диски находится в firmware-RAID, в частности, Intel RST RAID 1/10/5/6,
— если диск подключен по USB (ограничение протокола),
— если диск зашифрован программно через TrueCrypt, dm-crypt, GELI и т.п. (может поддерживаться, но обычно не включается по соображениям безопасности).

Если в результате тестирования выясняется, что диск не получает команду TRIM, то вскоре для записи может остаться совсем мало свободных страниц. Но они будут: каждый диск содержит некоторую зарезервированную область, которая служит как запас свободных страниц и запас блоков на замену полностью изношенным. Чтобы узнать размер этой области нужно посмотреть, какой физический объём памяти установлен на диске и сколько LBA указано в документации.

Например, Samsung SSD 840 Pro 512 GB имеет 512 ГБ памяти, при этом доступно 1000215216 LBA секторов. Резерв составляет: 512 × 1024 × 1024 × 1024 — 1000215216 × 512 = 35 ГБ или 6,85 %. Доступная ёмкость диска при этом составляет (512 — 35) × 1024 × 1024 × 1024 = 512 × 10^9 = 512 ГБ, уже десятичных. Samsung SSD 850 Pro 128 ГБ имеет на борту 129 ГБ, пользователю доступно 128 ГБ десятичных, резерв — 7,6 %.

Итак, если мы заполним весь диск, потом удалим все файлы, то без поддержки TRIM диск сможет писать только на какую-то часть от 6,85 % объёма диска. Часть, потому что этот резервный объём будет частично состоять из не полностью пустых блоков из-за фрагментации. Наличие этой области позволяет хоть как-то продолжать перезапись файлов на диске.

Пример худшей ситуации: писать некуда, хотя объём занятых страниц не превышает доступный пользователю без резерва.



В этом случае одновременно с записью работает сборщик мусора, который будет читать блок в оперативную память, стирать блок на диске (долгая операция, стирание занимает 3000 мкс в сравнении с 900 мкс записи в пустую страницу) и записывать блок из оперативной памяти. Задержка происходит также из-за роста Write Amplification — на одну логическую операцию записи приходится 5-10 физических операций записи.

Поэтому чем больше у диска есть свободного места для манёвров, тем выше скорость записи. Сборщик мусора в фоне занимается не только очисткой и дефрагментацией блоков, но и равномерным распределением циклов записи/очистки (P/E) по блокам, чтобы они изнашивались одинаково.

Есть популярный миф, что у современных дисков настолько хороший сборщик мусора, что им не нужен TRIM. Это совершенно не так, сборщик мусора и TRIM решают разные задачи.

Промышленные диски часто имеют 50% и больше резервной области, поэтому для них отсутствие TRIM не критично. Остальные диски чаще всего вообще не имеют явно заявленной резервной области, или она недостаточна. Тесты показывают, что хороший эффект имеет объём over-provisioning 25-29 % от общего объёма физической памяти (включая резервную область). Поэтому если у диска недостаточный объём резервной области, то нужно сделать over-provisioning самостоятельно.

Есть три способа:
— разметить диск таким образом, чтобы оставить некоторую часть неразмеченной области, после создания RAID,
— использовать команду ATA для создания Host protected area (howto), до создания RAID,
— настроить RAID контроллер, чтобы он использовал только часть объёма диска.



Прежде чем выделить свободную область, нужно дать знать диску, что эта область ничем не занята, одним из двух способов:
— подключить диск к другому контроллеру и послать команду ATA TRIM (или при помощи O&O Defrag — есть cli интерфейс, Windows 8 встроенный оптимизатор дисков или Anvil's Storage Utilities),
— сделать полную очистку таблицы FTL, послав команду ATA Secure Erase.

Есть версия, что также можно заставить диск понять, что блоки не используются, если туда записать 0x00 или 0xFF (так называемый метод «Tony TRIM»). Возможно, для каких-то контроллеров это работает, но мои тесты не показали изменений.

На практике


У меня есть два диска Samsung SSD 540 Pro 512 GB в Intel RST RAID 1, на которых установлена Windows 8.1. После года работы я измерил производительность и был неприятно удивлён. После проверки TRIM я увидел, что он не работает.

Проверка TRIM под Windows,
— Проверка TRIM под Linux:
# lsblk -D
Колонки DISC-GRAN и DISC-MAX обе должны быть больше 0 для всех участвующих компонентов.

Альтернативный вариант:
# dd if=/dev/urandom of=tempfile bs=1M count=3
# hdparm --fibmap tempfile
# hdparm --read-sector [ADDRESS] /dev/sda
# rm tempfile && sync && sleep 120
# hdparm --read-sector [ADDRESS] /dev/sda
После удаления файла на диске должны быть 0x00 или 0xFF, но это недостоверный способ: разные диски ведут себя по-разному.

TRIM в реальном времени включается опцией «discard» при монтировании диска:
# grep -i discard /etc/fstab
# mount | grep -i discard

TRIM для файловых систем на одиночных дисках и LVM поддерживается с ядра Linux 2.6.33. TRIM для mdraid поддерживается с ядра Linux 3.7. Но может быть портирован и на старые версии ядра, например, поддерживается в CentOS 6.

По-умолчанию Ubuntu делает TRIM по расписанию раз в неделю при помощи fstrim, но только для одиночных дисков (не mdraid) следующих производителей: Intel, Samsung, OCZ, SanDisk и Patriot и если установлен «hdparm».

— Проверка TRIM в FreeBSD:
ZFS по-умолчанию поддерживает TRIM начиная с версии FreeBSD 9.2:
# sysctl -a | grep -i 'zfs.*trim'

GEOM RAID gmirror поддерживает TRIM с FreeBSD 9.1:
gstat -d
колонка «d/s» — BIO_DELETE/second.

Intel RST RAID поддерживает TRIM только для типа RAID 1, как исключение: для включения нужно убедиться, что драйвер Intel RST версии 11 и выше, и прошивка OROM (Legacy boot) или SataDriver (UEFI boot) версии 11 и выше, или старая версия, но пропатченная. TRIM поддерживается в Intel RSTe RAID 0/1/10 начиная с версии 3.7.0.1093.

Я решил создать неразмеченный раздел диска для over-provisioning.
1. При помощи Acronis Backup я снял образ диска. Также сохранил таблицу разделов (важно иметь первый сектор, последний сектор, GPT тип раздела, GPT уникальный идентификатор, имя раздела).

2. Перезагрузился в BIOS и сделал SSD Secure Erase. Если этого пункта нет в BIOS, то можно выполнить команду при помощи hdparam (или здесь и здесь, есть под Windows), HDDErase или HDAT2.

3. Собрал RAID 1 на двух дисках.

Здесь нужно сделать важное замечание: при инициализации массива RAID-контроллер считывает каждый сектор с одного диска и записывает его на второй. Теоретически это должно помешать всей нашей затее, и на одном диске не будет over-provisioning. Но тесты показали, что этот метод почему-то работает. У меня этому нет объяснений.

4. Загрузился с LiveCD и при помощи GPT fdisk создал нужную таблицу разделов: последний раздел на 104 ГБ меньше, чем раньше. Разделы нужно выравнивать (partition align) по размеру страницы диска, а не по размеру блока.

5. Восстановил из резервной копии каждый раздел.

После этого я полностью заполнил диск и запустил тесты. Это должно показать худший случай. Кеш Windows включён, регулярная запись кеша выключена, Inter RST write-back выключен, все тесты используют область диска фиксированного размера в 40 ГБ. Тестировать диски непросто, поскольку показатели могут меняться во времени. Ниже сведены показатели установившегося состояния.

Я сравню три состояния:
— Один диск без RAID, полностью заполненный, стандартная скрытая резервная область 6,58 %.
— Один диск без RAID, после запуска на нём TRIM свободного места.
— Два диска в RAID 1, полностью заполненные, стандартная скрытая резервная область 6,58 %.
— Два диска в RAID 1, полностью заполненные, over-provisioning 27,24 % (включая скрытую резервную область).


Латентность и стандартное отклонение

Таблица


Анализ результатов:
— чтение с RAID 1 оказывается быстрее, чем с одного диска, невзирая на то, что у нас всего лишь firmware RAID.
— запись тем быстрее, чем больше нераспределенного пространства: на первом месте TRIM, на втором — наш самодельный over-provisioning.

Установившееся состояние не всегда достигается быстро. Посмотрим тест последней конфигурации (over-provisioning 27,24 %) в динамике и увидим худший случай:





Любопытный процесс идёт первые 400 секунд, после чего производительность возрастает и стабилизируется. Я думаю, параллельно с записью работает сборщик мусора, который дефрагментирует блоки и подготавливает их для записи. Такое поведение наблюдается не каждый раз, а время от времени. Видно, что последовательная запись проседает до 70 МБ/с, случайная запись — до 18000 IOPS. Эти показатели всё равно в два раза лучше, чем без over-provisioning (32 МБ/с и 7139 IOPS соответственно). Чтобы убедиться, что установившееся состояние на самом деле имеет такую высокую производительность, я также выполнил тест в течении 30 минут, при этом было записано на диск 490 ГБ со средним 69721 IOPS.

Можно сравнить наши результаты с коллегами и выбрать оптимальный размер over-provisioning:

Кратко


— Если диск получает ATA TRIM от ОС, то беспокоиться не о чем, достаточно оставлять часть места на диске свободным.
— Если используются дорогие промышленные диски, то проверьте объём встроенной резервной области, если он достаточен, то проблем с записью не будет.
— В остальных случаях нужно оставить не размеченную область, чем больше её размер, тем меньше будет стандартное отклонение латентности записи.
— Иногда сборщик мусора не успевает подготовить чистые блоки и скорость записи может просесть и быть непостоянной.
— После over-provisioning установившаяся максимальная скорость записи повысилась с 7000 до 68000 IOPS, а средняя минимальная — с 6000 IOPS до 19000 IOPS.

Tags:
Hubs:
+63
Comments 74
Comments Comments 74

Articles