понедельник, 22 апреля 2013 г.

SSD

Всё что вы таки хотели знать, и побоялись спросить.

История

На самом деле, твёрдотельные накопители известны с древнейших времён. Ещё в ZX Spectrum использовались "флешки", а точнее EEPROM. Данная память являлась энергонезависимой, т.е. при отключении питания информация в ней сохранялась. Удалить её не было никакой возможности в штатном режиме.

Конструкция

Сама по себе EEPROM являлась матрицей из самых обычных МОП транзисторов. За одним интересным исключением: данный транзистор имел карман над затвором, т.е. некоторую изолированную область. Если она была пуста (т.е. как соседние слои кремния), то никакого эффекта от неё не было. Транзистор проводил ток,  что трактовалось как 1. Но если-бы в кармане присутствовали заряды, он-бы тогда работал как затвор,  и его заряд отклонял-бы поток носителей (электронов/дырок) в канале МОП транзистора. Такое состояние условно обозначается как 0.

Запись

Для записи в ячейку используется туннельный эффект, который можно представить как обратимый пробой изоляции кармана. Для этого на карман подают высокое напряжение (+12V например, как в упомянутом ZX), за счёт чего электроны и попадают в т.ч. и в этот карман.

Записывать можно исключительно нулевые биты, ибо нет никакого способа сделать из 0 →   1. В начальном состоянии все биты имеют значение 1, и при записи, некоторые из них переходят в 0. Очевидно, что если EEPROM может записывать только нули, то в начальном состоянии все байты содержат 0xFF, и перевести их можно в конечном итоге не далее, чем в 0x00. Именно по этой причине, в системе команд тех CPU код 0x00 означал NOP (нет операции).

Умножитель

Использовать два источника питания (+5В и +12В) было естественно неудобно. Потому к концу 80х годов прошлого века, изобрели второй раз умножитель напряжения. Этот девайс работает по совсем простому принципу: заряжает несколько конденсаторов параллельно, а затем разряжает последовательно, получая высоковольтный импульс напряжением, которое пропорционально числу конденсаторов. Таким образом и получался высоковольтный импульс годный для записи.

Стирание

Первые чипы EEPROM не имели стирания вовсе. Однако, почти сразу было замечено, что облучение УФ светом выбивает электроны из карманов, приводя EEPROM в исходное состояние. Потому чипы стали делать с окошечком, через которое они собственно и стирались. Ресурс был не очень большой, ибо выходом из строя чипа считался выход любого его эл-та. А даже в первых вариантах эл-тов было порядка 128К. Таким образом ресурс составлял всего около сотни циклов записи (с учётом того, что после каждой записи нужно стирание).

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

NOR

Такие чипы NOR устанавливали во все компьютеры, начиная с первых IBM-PC. NORами они назывались по очень простой причине - все эл-ты были соединены параллельно, а стало быть выполняли функцию ИЛИ, однако, и-за того, что сам по себе транзистор выполняет функцию NOT (если есть напряжение на затворе, или в кармане, транзистор заперт, и ток через него НЕ течёт), то получившийся элемент выполнял функцию NOT-OR. Эти чипы практически были вечными, ибо читались всего один раз, во время загрузки. Затем ROM отключалась, и на работу компьютера не влияла. Однако, можно было стереть, и перезаписать прошивку, чем и пользовался вирус CIH. Для лечения требовалось вынуть флешку из здоровой мамки(такой же), вставить в больную, загрузится, по горячему поменять, и прошить больную флешку. Иногда такая беда возникала без всяких вирусов, сама по себе, и лечилась так же. Судя по этому опыту, можно сказать, что информация во флеш чипах может хранится как минимум десятилетиями, и вероятность потери ничтожно мала (и даже если мы потеряем какой-то бит, мы потеряем именно один бит, который можем и восстановить, и переписать).

NAND

NOR это конечно хорошо, но мало. Чтобы было больше, транзисторы можно построить столбиком, и соединить последовательно. Ток через такой столбик пойдёт в том, и только в том случае, если все транзисторы открыты, как затворами, так и карманами. Т.о. они выполняют логическую функцию NOT-AND. Побочный эффект очевиден - хотя в одном столбике и можно записать несколько бит, но вот прочитать за один раз можно только один. Впрочем, это не важно, т.к. всего у нас 100500 эл-тов, и прочитать их все сразу нет никакой возможности.

MLC

Ещё один путь повышения ёмкости (кроме NAND столбиков) - хранение в карманах не просто какого-то заряда, а несколько разных значений этого заряда. Такой метод называется MLC. Обычно в кармане хранят не два (0,1), а четыре уровня (00,01,10 и 11), что позволяет добиться хранения двух битов на одном транзисторе. Также можно хранить и 8 уровней(TLC), однако профит этого не настолько большой, и потому проще делать четырёхуровневые MLC(их больше влезает).

Болезни by design

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

  • одной из основных проблем флешек является низкое число циклов записи/стирания. Конечно это далеко не 100 циклов, но и 10000..100000 тоже немного для использования флешек вместо типичного ЗУ. Проблема кроется в том, что туннельный эффект, это тоже в некотором смысле пробой, и постоянная инжекция электронов в карманы ведёт к деградации их изоляции. Т.к. за каждой записью нужно стирание, то это также приводит к старению эл-тов. Мало того - стирать можно только целиком весь носитель, потому, даже если мы записали немного, то для повторной записи придётся стереть всё. Для устранения этой проблемы пришлось ввести контроллер, который выбирает для записи всякий раз новые страницы, дабы запись не осуществлялась в одно и то же место. Кроме того, современные флешки уже не стираются полностью, а могут стираться отдельными островами. Сегодняшние SSD могут теперь похвастаться огромным ресурсом, и это уже НЕ является особой проблемой. Однако важно всё же помнить о том, что для нормальной работы SSD необходимо свободное пространство, ибо если его не будет, контроллер будет просто вынужден использовать только очень небольшой объём, который и будет планомерно задрачивать(и который быстро выйдет из строя). Конечно, во внешних ЗУ 1 мегабайт равен 1 000 000 байт, хотя на самом деле 1048576 байт. Потому небольшой резерв есть всегда. Но, ИМХО, для надёжной работы администратор просто обязан обеспечить некоторое свободное место. Если у вас Windows™, вы можете просто разметить SSD так, что-бы была какая-то неразмеченная область (чем больше, тем лучше для ресурса). Для Linux с этим вопросом проще, если вы используете ручное разделение на разделы (всё равно требуется выделять с запасом).
  • Вторая важная проблема: низкая скорость записи и стирания. Скорость записи в настоящее время весьма велика, и составляет примерно 40..20% от скорости чтения. Это обеспечивается исключительно тем, что запись происходит одновременно в несколько островов. Ещё один повод выделить достаточно свободного места, ибо очевидно, что если остров всего один, ни о какой параллельной записи не может идти речи. Низкая скорость стирания связана с работой умножителя, который требует длительной зарядки ёмкостей. (см. выше). Практически неустранима на сегодняшний день, однако, её можно делать в фоне(см. далее).
  • "Усиление записи". Выше я уже писал о том, что страницы на SSD организованы в острова, которые можно стирать только полностью, всем островом. Это приводит к тому, что каждая страница может находится в трёх состояниях: Во первых страница может быть чистой, и готовой к записи. Во вторых страница может содержать нужные данные, и в третьих страница может содержать уже ненужные данные. Возможна ситуация, когда на острове все страницы находятся в состояниях 2 или 3. И несмотря на то, что страницы в состоянии 3 уже не нужны, остров невозможно очистить из-за страниц в состоянии 2. Потому возможна ситуация, когда свободное место есть, но писать данные некуда.

TRIM

Для решения всех этих трёх проблем, первоочередное место занимает число свободных островов. Если у вас  их много, то никаких проблем нет. Однако, современные ФС не стирают информацию при её удалении, для HDD/FDD это просто не нужно. Посему, большинство страниц рано или поздно зависает в состоянии 3, и требует очистки. При этом, страницы в состоянии 2 требуют перемещения на свободные острова. Это можно всё выполнить в фоне, если использовать новую ATA команду TRIM.

Следует помнить, что команда TRIM сама по себе ничего не стирает. Она лишь уведомляет носитель о том, что страница перешла из состояния 2(с данными) в состояние 3(грязная). Само по себе стирание осуществляется лишь сборщиком мусора(GC), который переносит нужные страницы на свободные острова, а потом стирает те острова, где грязных страниц больше всего. Это может занять длительное время, которое тем не менее никак не сказывается на скорости работы (если достаточно чистых страниц).

Страницы также могут быть опознаны носителем в состоянии 3, в том случае, если мы осуществляем повторную запись в страницу, которая находится в состоянии 2. Запись при этом осуществляется в какую-то другую страницу (чистую), а эта помечается как ненужная. В таком режиме чистые страницы очень быстро закончатся, и скорость записи катастрофически упадёт (что мы и видим на фешках). Тоже самое будет и с SSD, если не включить команду TRIM. Проблема ещё и в том, что у сборщика мусора в данной ситуации нет ни времени, ни места, и потому его эффектность близка к нулю - он слишком много пишет и стирает. Это сильно уменьшает ресурс носителя.

В нормальной ситуации проблемы нет, т.к. GC успевает загодя заготовить достаточное количество свободных островов(если конечно свободного места достаточно).

Рекомендации и мифы

Основная рекомендация: свободное место. Его должно быть МНОГО. В идеале 40%, хотя можно и поменьше, но не менее 25% носителя. Следует помнить о том, что фундаментальные истины не стареют: ещё Кнут доказал, что ЛЮБОЕ ЗУ начинает тупить, если сильно заполнено (более 90%). Потому не нужно думать, что вы выбрасываете мегабайты на ветер. НЕ ЖАДНИЧАЙТЕ. В конце концов, сейчас мегабайт стоит копейки, даже если это RAM, а тем более SSD.

Вторая рекомендация: TRIM. Все современные ФС это умеют (man mount на предмет discard для ext4), и этим НАДО пользоваться. Без TRIM вы мучаете свой SSD, не нужно этого.

Как не странно, что касается записи, то это всего лишь третья рекомендация. Да, лишних записей не нужно. Но и фанатизма тоже не надо. Скажите спасибо ненастраиваемой Windows™, благодаря которой, SSD сейчас допускают бешеное количество циклов записи.

Однако, есть смысл таки прикупить памяти, и смонтировать туда /tmp/. Этот каталог не нужен при перезагрузке, да и его можно использовать для компиляции, распаковки (напосмотреть), и прочих временных нужд. Даже с SSD память всё равно в разы быстрее. Ну и зачем мучить SSD, если без этого можно обойтись? С т.з. безопасности /tmp тоже желательно выкинуть в память, ибо удаление в SSD никем и никогда не гарантировалось, потому враги могут в принципе отыскать ваши пароли/ключи в грязных блоках.

С другой стороны, другие каталоги выносить в память не нужно. Если конечно на это нет очень веской причины. Запись туда не настолько частая, и для десктопа потребуется десятки лет, дабы сжечь ресурс современного SSD.

Мало того, если вы вынесете всякие кеши и т.д. в память, это может привести лишь к тормозам, и сильному износу SSD. Почему? А потому, что SSD отлично работает на чтение, и если ваш браузер что-то там закешировал, есть смысл это прочитать с кеша, чем грузить вторично из интернета.

Тоже самое касается noatime, которая тоже не нужна. Почему? А потому, что именно по времени доступа ваш браузер и другие программы судят о нужности или не нужности закешированного файла. Если atime маленькая, значит файл не нужен (мы его давно не использовали), и его можно удалить, а освободившееся место использовать для нужного. Если вы поставите noatime, вы всё поломаете, и программы будут удалять нужные файлы, которые они постоянно используют. А сразу вслед за этим скачивать их повторно из интернета, и губить этим ваш SSD (ну и тормозить для комплекта).

SWAP

Своп не нужен, но должен быть. Странно, да? Ничего странного: в нормальном режиме своп не нужен, если он у вас используется: goto за новой памятью. Или мучайтесь с тормозами. А зачем своп? А нужен своп за тем, дабы у системы было немного времени на раздумья, кого надо убивать за перерасход памяти. Такое бывает. Такое бывает даже с хорошими программами в странных условиях. И если свопа нет, то для системы это равносильно как для вас топором по голове. Если своп есть - OOM Killer успеет выяснить виновника, и убить его. На сервере это критически важно. На десктопе - это просто неудобно, когда ВНЕЗАПНО иксы падают, и у вас чёрный экран. Да, ничего не сохранилось конечно. Вам это надо?

Размер свопа не нужно делать большим. В принципе достаточно 512Мб(для десктопа), но из-за наличия свободного места для SSD, его можно сделать и побольше. Вплоть до полного объёма памяти, дабы обеспечить засыпание.

Нужно-ли отключать планировщик записей на диск? Нет. Вам делать нечего? Ну отключите, вот только не забудьте о том, что SSD разрабатываются в расчёте на то, что этот планировщик таки работает.

Нужен-ли commit=xx? Не нужен. С ним вы потеряете свою работу за последние xx секунд, без него ваш носитель будет работать не 6472 дня, а 6451 день. Выбирайте сами, что вам дороже.

Нужно-ли сувать в память кеш пакетного менеджера? В принципе нужно, если вам нравится сидеть и смотреть, как оно это всё выкачивает по 10 раз.

Нужно-ли отключать журналирование? Нужно, если вы хотите ЗАГУБИТЬ СВОИ ДАННЫЕ И СИСТЕМУ. Для SSD это тем более важно, ибо данные на SSD носителе, хоть и раз в 10 лет, но таки иногда портятся. Без журнала это похоронит нах всю файловую систему.

Ну и наконец: "почему у меня не работает TRIM?" Ответ: см. hdparm -I /dev/sdX. Если там пишет - "работает", значит работает. Ну и конечно discard для ext4 включите (в других ФС я не знаю как). Если у вас всё в 0xFF не вставляется - это не повод для беспокойства, оно не сразу. Народ говорит, что в некоторых SSD вставляет в 0x00, это не страшно, 0 и 1 это условности. Главное - вставляет.

6 комментариев:

  1. Годно, интересно, спасибо.

    ОтветитьУдалить
  2. Скрипт для проверки TRIM , очень полезная штука так как узнать работает ли TRIM можно только по факту

    #!/bin/bash
    #
    # Test if TRIM is working on your SSD. Tested only with EXT4 filesystems
    # in Ubuntu 11.10 and Fedora 16. This script is simply an automation of
    # the procedures described by Nicolay Doytchev here:
    #
    # https://sites.google.com/site/lightrush/random-1/checkiftrimonext4isenabledandworking
    #
    # Author: Dorian Bolivar
    # Date: 20120129
    #

    if [ $# -ne 3 ]; then
    echo
    echo "Usage: $0 "
    echo
    echo " is a temporary file for the test"
    echo " is the file size in MB"
    echo " is the device being tested, e.g. /dev/sda"
    echo
    echo "Example: $0 tempfile 5 /dev/sda"
    echo
    echo "This would run the test for /dev/sda creating a"
    echo "temporary file named \"tempfile\" with 5 MB"
    echo
    exit 1
    fi

    FILE="$1"
    SIZE=$2
    DEVICE="$3"

    # Create the temporary file
    dd if=/dev/urandom of="$FILE" count=1 bs=${SIZE}M oflag=direct
    sync

    # Get the address of the first sector
    hdparm --fibmap "$FILE"
    SECTOR=`hdparm --fibmap "$FILE" | tail -n1 | awk '{ print $2; }'`

    # Read the first sector prior to deletion
    hdparm --read-sector $SECTOR "$DEVICE"
    echo
    echo "This is a sector of the file. It should have been successfully read"
    echo "and show a bunch of random data."
    echo
    read -n 1 -p "Press any key to continue..."

    # Delete the file and re-read the sector
    rm -f $FILE
    sync
    echo
    echo "File deleted. Sleeping for 120 seconds before re-reading the sector."
    echo "If TRIM is working, you should see all 0s now."
    sleep 5
    hdparm --read-sector $SECTOR "$DEVICE"
    echo
    echo "If the sector isn't filled with 0s, something is wrong with your"
    echo "configuration. Try googling for \"TRIM SSD Linux\"."
    echo

    exit 0

    ОтветитьУдалить
  3. С noatime всё более-менее понятно. Как насчет relatime, который довольно часто советуют? В случае записи atime обновляется. LRU-cache, конечно, делать менее удобно. Но так ли часто они делаются на основе atime?

    Насчет выноса директорий в память каноническим примером является кэш хрома/хромиума, в который запись довольно интенсивная. Есть готовые утилиты типа profile-sync-daemon'а.

    ОтветитьУдалить
    Ответы
    1. >Как насчет relatime, который довольно часто советуют?
      relatime конечно более разумный выбор(чем noatime), с такой опцией ФС не лезет на каждый чих обновлять метаданные. Не могу посоветовать ставить её всем и всегда, но ИМХО в большинстве случаев это полезно сделать. Во всяком случае особого вреда от этого я не вижу.

      Вообще говоря, все эти опции имеют смысл лишь для директорий, в которых МНОГО файлов, и которые к том-же постоянно используются. ИМХО если таких директорий нет, то и не нужно заморачиваться. Ну а если есть, то есть смысл ВООБЩЕ запретить туда запись (mount -o ro например), к примеру я так поступил с /usr, которая занимает значительное место, и которая изменяется очень редко, только при обслуживании системы.

      >Насчет выноса директорий в память каноническим примером является кэш хрома/хромиума, в который запись довольно интенсивная. Есть готовые утилиты типа profile-sync-daemon'а.
      ага, спасибо. Возможно это кому-то поможет. Хотя у меня хром и так летает, и я не вижу особенного смысла в выносе кеша(в моём конкретном случае). Но это может пригодится в слабых мобильных системах.

      Удалить