Wheezy
Newbie | Редактировать | Профиль | Сообщение | Цитировать | Сообщить модератору Достаточно часто приходится слышать, что твердотельным накопителям дефрагментация не нужна. Иногда это ошибочное мнение пытаются обосновать достаточно странным соображением, что "в SSD нет движущихся частей, поэтому скорость доступа к любой ячейке одинакова". Могут еще добавить "как в оперативной памяти". Хотя именно время доступа к ячейке ОЗУ в зависимости от адреса может отличаться более, чем на порядок. Почему? Потому что надо произвести трансляцию адресов. В современных процессорах архитектуры х86 она трехуровневая. А с использованием расширенной таблицы страниц (EPT) и вовсе 5-тиуровневая. И прежде чем прочитать слово из оперативной памяти необходимо загрузить таблицу страниц для каждого из этих уровней если этой таблицы в данный момент нет в кэше TLB. Как обстоит дело на самом деле? Вообще говоря, в отличие от жестких дисков, дефрагментация для твердотельных накопителей принципиально необходима. Именно поэтому делают её редко. Эта фраза только звучит парадоксально. Ведь вследствие своей жизненной важности для SSD эта процедура встроена в микропрограмму контроллера накопителя и является одной из составных частей процедуры "сборки мусора" FTL (flash translation layer). Однако, эта процедура позволяет устранить только один из видов фрагментации - так называемую внутриблоковую фрагментацию. Этот вид фрагментации вызван тем, что размеры размеры минимального объема данных для чтения/записи и стирания не совпадают. Жесткий диск это устройство с прямым отображением информации. По номеру логического блока можно определить номер стороны/дорожки/сектора на дорожке. Да, и у жесткого диска есть какая-то небольшая ассоциативность в виде таблиц транслятора, но они малы по размерам и статичны. Переадресация применяется только в случае появления дефектного блока. Если компьютер обращается к контроллеру HDD с требованием изменить какой-то блок на диске, тот просто записывает новую информацию поверх старой и на этом всё заканчивается. Что происходит в твердотельном накопителе? Для SSD номер логического блока это просто метка присвоенная какой-то из страниц флеш-памяти. Причем это отображение чрезвычайно лабильно - при каждой записи одному и тому же логическому блоку будет соответствовать новая страница. Значит во-первых, надо где-то хранить таблицу трансляции логических адресов в физические, а во-вторых при каждой записи её модифицировать. Значит там, где HDD выполняет единственную запись, SSD должен выполнить несколько. Причем объем данных которых необходимо переместить для записи единственного блока может быть настолько велик, что твердотельный накопитель может стать заметно медленнее жесткого диска. Почему же мы этого не замечаем? Почему подобные результаты крайне редко встречаются в результатах тестов? Потому что всю необходимую запись для перемещения данных SSD выполняет в фоновом режиме уже после того как пользователь дал команду что-то записать. Но если тестировать SSD под нагрузкой в течение достаточно долгого времени (я с таким сталкивавлся в среднем через 4-6 часов интенсивной работы, хотя этот срок зависит от массы факторов), производительность SSD резко падает. Одним из упомянутых факторов является объем свободного места на накопителе. Чем он больше, тем легче контроллеру находить свободные физические блоки для записи. Поэтому в промышленных SSD этот объем может доходить до 40%. Представляете? Чуть больше половины объема выделяют пользователю, остальное остаётся для внутренних нужд контроллера. Чтобы понять почему SSD жизненно необходимо свободное место, которое контроллеру HDD абсолютно без надобности, давайте рассмотрим пример того, что происходит внутри SSD при изменении, скажем, таблицы разделов в MBR накопителя. Главная загрузочная запись имеет фиксированный номер логического блока - 0. Предположим для простоты, что у нас есть диск объемом 120ГБ (реально он конечно 128ГиБ, из которых пользователю выделено 120 десятичных гигабайтов) с размером страницы 8 кБ и физического блока 512 кБ. То есть в одном физическом блоке содержится 128 страниц. Мы изменяем содержимое нулевого блока. На HDD этот блок был бы просто записан в соответствующее место поверхности. Но перезаписать страницу SSD без стирания всех остальных страниц физического блока к которому относится страница нельзя. Так что же, стирать все 512 кБ ради записи 512 байт? Нет, конечно. Этого никто не делает. Во-первых, операция стирания очень медленная - она занимает единицы миллисекнд. Во-вторых, она влечет за собой износ поверхности связанный с протечкой электронов в затвор из-за деградации диэлектрика. Раз стирать нельзя, то что делать? Модифицированная страница записывается на свободное место, а старая версия помечается как "грязная". Сразу отметим, что после такой записи данные на SSD начинают занимать больше места, чем на жестком - контроллер расходует на это один из свободных блоков. Значит если на SSD не оказалось бы свободных блоков, на него ничего невозможно было бы записать. Но вы с таким никогда не столкнетесь. Ведь, как мы уже отметили, кроме доступного пользователю пространства на SSD зарезервирован достаточный объем под нужды контроллера. Итак, мы уже имеем две записи вместо одной. Ведь надо отметить старую страницу как использованную, но не очищенную и выделить новую. Однако, на этом дело не заканчивается. Как мы уже выяснили, SSD это устройство с ассоциативной памятью. Значит необходимо изменить еще и L2P таблицу. Таблицу отображения логических адресов в физические. То есть число необходимых операций еще больше растет и становится равным как минимум трём. Почему "как минимум"? Об этом чуть позже. Для начала давайте представим себе, что следом за MBR мы изменили еще одну страницу. Страница, напомню, в нашем случае имеет размер 8 кБ. Это достаточно типичный размер для SSD хотя она часто бывает и 4, и 16 кБ. Старое содержимое страницы опять было помечено как недействительное, а новое опять куда-то записано. Куда? Опять брать для записи блок из пула свободных? Этак никакого резерва не хватит. Куда эффективнее записать эту страницу в тот же блок, в который ранее была записана новая копия MBR. И тут очень важно научиться различать физические блоки накопителя (напомню, в нашем случае они равны 512 кБ), страницы и те старые привычные нам логические блоки в терминах которых мы привыкли обращаться к жесткому диску. Понятно, что когда я говорю про "тот же блок", имеется в виду не LBA, а некий полностью скрытый от нас номер физического блока. Не все пользователи правильно понимают смысл процедуры стирания физического блока SSD, поэтому позволю себе пояснить, заранее извиняясь перед более опытными людьми для которых это очевидно: стирание блока похоже на стирание написанного на классной доске. Стираешь один раз, а писать потом можно многократно. Но только на свободных местах. Если у нас блок 512 кБ, а страница 8 кБ, мы можем после одного стирания писать в этот блок до 64-х раз, но каждый раз должны записывать новую страницу. Итак, мы записали страницу в тот же блок в котором ранее сохранили копию MBR. Что у нас физически получилось в микросхемах NAND? (вопрос о том почему никто не использует NOR мы рассматривать не будем) У нас есть два физических блока в которых страницы идут последовательно (оба с "дырками" на месте старых копий страниц) и один блок с произвольным расположением страниц. Как понять "последовательно" и "произвольно". Очень просто. В исходном физическом блоке LBA 0 отображался на самую первую (или, если вы программист, на нулевую) страницу. LBA 1 - на следующую, потом LBA 2, 3 и так далее. Конечно, при условии, что размер логического блока равен размеру страницы, хотя чаще всего это не так, что создает дополнительные проблемы от фрагментации. Описанный выше блок называется блоком данных (data-block). В то время как во втором описанном типе блоков (обратили внимание как легко перепутать LBA и физические блоки?) страницы записываются не последовательно, а в более-менее произвольном порядке. При типичной для SSD полностью ассоциативной записи такой порядок может быть полностью произволен. В одной странице хранится LBA 0, в следующей 0x1000, потом опять 0, только следующая копия (первая при этом объявляется недействительной) и так далее. Такой блок называется журнальным (log-block). Понятно, что измененные данные куда удобнее хранить в журнальных блоках, чем упорядочивать их каждый раз, преобразуя журнальные блоки в блоки данных. Почему же этого обычно не делают? Потому что это потребует огромного количества места для хранения индексов. В самом деле, для каждой страницы журнального блока надо хранить как минимум 4 байта того номера LBA который в данный момент в ней записан. Значит 1/2048-ая часть диска (4 байта на каждые 8кБ данных) будет занята транслятором. Вроде бы совершенно не страшно. Но есть одна деталь - транслятор желательно постоянно хранить в оперативной памяти. Чтобы не читать его с диска каждый раз. Нет, не в оперативной памяти компьютера, а в буферной памяти накопителя. Она намного меньше по размерам и хранить там транслятор просто накладно. Давайте сами подсчитаем: для нашего гипотетического 128 ГБ SSD полностью ассоциативный транслятор занял бы 64 МБ. Это могло бы быть, скажем, половиной всего имеющегося у него объема. Чересчур расточительно расходовать столько памяти на единственную, пусть и самую важную таблицу. Поэтому наиболее распространенным типом FTL является гибридный. Любой блок может быть как блоком банных, так и журнальным, но общее количество журнальных блоков ограничено. И здесь необходимо отметить еще один момент. К сожалению, технология SSD обеспечивает достаточно низкий уровень сохранности записанных данных. А представьте себе, что произошёл сбой при чтении L2P таблицы. Или просто ошибка и вместо страницы где хранится нужный вам блок прочитали другую в которой был блок с совершенно другим номером, что тогда? А ничего страшного. Все производители, записывая данные в накопитель, кроме самих данных записывают еще и LBA который им соответствует. Контроллер просматривает L2P таблицу и выбирает из неё элемент соответствующий заданному LBA, Содержимое этого элемента соответствует номеру страницы. Он читает эту страницу и, одновременно, тэг этой страницы. В котором, помимо всего прочего, хранится копия номера логического блока ("блок" в данном случае используется в смысле LBA). Просто. Удобно. Надежно. Но еще раз увеличивает количество операций чтения/записи при доступе к данным. Заметили, что это число растет как грибы? Но ведь в результате всего вышеописанного у нас на накопителе нарастает беспорядок. В блоках образуются дырки, растет число журнальных блоков, уменьшается количество свободных. Значит должна быть какая-то процедура уборки, которую SSD может выполнять в свободное от основной работы время. Эту процедуру мы уже упоминали. Она называется сборкой мусора (garbage collection) и хорошо знакома любому программисту. Основная цель этой процедуры заключается в устранении фрагментации. Все блоки с "дырками" и журнальные блоки преобразуются в блоки данных, а занимаемое ими ранее место возвращается в пул свободных блоков (мы уже выяснили, что фрагментированные данные физически занимают больше места на накопителе). Казалось бы, ничего сложного. Сканируешь цепочку блоков, находишь фрагментированный, читаешь все фрагменты в буфер и записываешь на новое место. Старые копии помечаешь как недействительные. Если какой-то блок целиком содержит только удаленные страницы его можно спокойно стереть в свободное время и добавить к пулу свободных. Спрашиваете, зачем я это всё пишу, это и так всем понятно? По двум причинам. Первая касается SATA команды TRIM (и аналогичной SCSI UNMAP). Что она делает? Часто приходится слышать, что она стирает содержимое блока. И, кстати, после её использования блок действительно читается как заполненный нулями. Но это фикция. На самом деле она всего лишь устанавливает флаг "удалена" в тэге страницы. И контроллер вообще не видит смысла после этого производить действительное чтение. Реально удалить одну-единственную страницу с твердотельного накопителя невозможно - надо очищать весь физический блок (в нашем случае маленький - 64 страницы, обычно он больше). Теперь вторая причина, которой мы до этого еще не касались. Контроль износа поверхности. Wear leveling. У любого из вас данные на SSD можно условно разделить на два типа - практически неизменяемые, которые были записаны один раз когда-то давным-давно и те, которые постоянно перезаписываются. Такие как файл/раздел подкачки. Если в процессе процедуры сборки мусора мы будем помещать в пул свободных блоков только те, которые освободились в результате дефрагментации, это приведет к тому, что часть ячеек SSD будет перезаписываться постоянно, в то время как другие, напротив, не будут перезаписываться никогда. И те, которые стирали слишком много раз, быстро начнут выходить из строя. Но в действительности, как мы все знаем, ячейки даже заполненного почти до отказа накопителя (а у домашних пользователей они почти все такие) изнашиваются примерно с одинаковой скоростью. Почему? Потому что опять-таки в свободное время контроллер переносит редко изменяемые данные в самые изношенные блоки. потом допишу, надоело... А может и не допишу. Поэтому коротко самое главное: может показаться, что скорость случайной записи на SSD должна быть равна скорости последовательной. Это абсолютно не так. Даже если посмотреть на сайте производителей, в этом легко убедиться. Давайте взглянем на какой-нибудь из SSD производства Intel для конечного потребителя: https://www.intel.ru/content/www/ru/ru/products/memory-storage/solid-state-drives/consumer-ssds/540s-series/540s-240gb-2-5inch-6gbps-16nm.html (надеюсь меня не заподозрят в том, что я рекламирую продукцию Intel?) Обращаем снимание на строчку: Цитата: Случайное чтение (участок 8 ГБ) (в пределах) | То есть чтение произвольных блоков, но все блоки должны лежать в одном заданном диапазоне логических адресов. Для промышленных SSD Intel указывает более важную характеристику - доступ к блоку с любым логическим номером. https://www.intel.ru/content/www/ru/ru/products/memory-storage/solid-state-drives/data-center-ssds/dc-p4600-series/dc-p4600-4tb-aic-3d1.html Цитата: Случайное чтение (участок 100%) | Почему доступ в пределах какого-то ограниченного участка (в случае Intel 8ГБ) осуществляется быстрее? Каждая запись в L2P таблице может иметь размер 32 бита. 4 байта. Накопители Intel имеют типичый размер страницы 8 кБ. Значит в каждой странице содержится 8096/4=2048 записей. Эти записи охввтывают диапазон 2048*4кБ=8192МБ. Те самые 8 ГБ. То есть это тот диапазон доступ к которому не требует дополнительного считывания/модификации страниц транслятора. Насколько дополнительные чтение/запись могут замедлить работу накопителя? Измеренная скорость произвольной записи в любое место накопителя (LBA span 100%) примерно в 9-10 раз ниже последовательной записи. Правда, никак не согласуется с утверждением "SSD не имеет механических частей, пишите куда хотите"? Скорость чтения это более сложный вопрос. Как правило, на реальных накопителях произвольное чтение оказывается примерно в 2-3 раза медленнее, чем последовательное. Не буду притворяться, что понимаю почему это происходит. Причин, как и с записью, скорее всего несколько и вряд ли кто-то кроме инженера занимающегося разработкой таких накопителей может назвать их все. Могу только предположить, что это может быть связано как с пакетной передачей данных из микросхем памяти, так и предвыборкой логических блоков контроллером. Причем скорее со второй причиной, чем с первой. Ведь последовательные логические блоки очень быстро перестанут располагаться в последовательных физических. N.B. Всё вышеперечисленное не следует рассматривать как совет производить дефрагментацию SSD встроенными средствами ОС. Они рассчитаны на жесткие диски и, устраняя фрагментацию на уровне файловой системы, будут создавать огромный объем внутриблоковой фрагментации. Если хотите дефрагментировать SSD перенесите с него информацию на другой носитель (к примеру, HDD), реинициализируйте SSD и копируйте обратно. Это эффективно устранит все виды фрагментации, не создавая при этом излишнего износа поверхности. | Всего записей: 10 | Зарегистр. 21-09-2012 | Отправлено: 21:49 18-07-2017 | Исправлено: Wheezy, 22:35 19-07-2017 |
|