2013-05-01 Почему на флешки случайная запись медленная
Я до вчерашнего дня думал, что USB флешки и карточки памяти — это практически голая флеш-память. А оказывается, нет — любая флешка/SDшка/CFка имеет внутри себя тупой, но всё-таки контроллер с тупым, но всё-таки FTL’ем (Flash Translation Layer’ом), который даже умеет какой-то wear leveling.
Тупой контроллер потому, что мелкий и ресурсов у него мало. В частности — мало памяти. Именно из-за этой тупости случайная запись на флешки/SD/CFки так дико тормозит. Из-за малого объёма RAM контроллеру флешки, в отличие от контроллера SSD, негде хранить полную таблицу сопоставления виртуальных и реальных секторов. Поэтому мапятся не сектора, а крупные блоки по где-то мегабайту (бывает и больше), а при записи есть лимит на количество «открытых» блоков.
Как это происходит:
- Допустим, вы пишете в сектор X.
- Контроллер отображает блок, которому принадлежит этот сектор, на реальный блок, и «открывает» его — выделяет пустой блок, запоминает, что он «дочерний» для открытого и записывает туда один изменённый вами сектор.
- Таким макаром можно открыть максимум N разных блоков; N обычно очень маленькое — в районе 3-6. Вот у меня на столе лежит флешка, у которой 6.
- Дальше если вы пишете следующий сектор из уже открытого блока — он просто записывается в его дочерний блок (что быстро).
- Если же следующий записываемый сектор принадлежит другому блоку — какой-то из открытых блоков придётся закрывать и сливать содержимое дочернего блока с оригинальным.
При случайной записи секторов по всей флешке вы почти не попадаете в уже открытые блоки ⇒ каждая операция записи превращается в перезапись полного блока (что медленно). Опять-таки в отличие от SSD, которому пофиг и который группирует в физических блоках сектора из любых мест диска.
И поэтому авторы всяких UBIFS и JFFS2 не совсем правы, когда говорят, что эти ФС не предназначены для блочных устройств, а только для MTD (MTD — это как раз голая флеш-память). Ибо даже если смонтировать флешку в UBIFS через block2mtd, то скорость записи мелких файлов кардинально возрастает и становится вполне похожа на скорость нормальной последовательной записи. Это, может, и не совсем оптимально — UBIFS сама занимается стиранием блоков, а в случае USB флешки этого можно было бы не делать. Но всё равно она сильно быстрее, чем использование обычной НЕ лог-структурированной ФС.
У меня вот идея маленькую реплику MySQL повесить дома на флешку с UBIFS. Дело в том, что когда я прошлый раз пробовал повесить домой реплику с сервера, она меня достала постоянным шуршанием харда :)
Кстати, выяснить размер стираемого блока и лимит числа открытых блоков своей флешки можно утилитой flashbench и делением отрезка пополам:
- Размер блока
- запускаем flashbench -a /dev/sdc, смотрим на вывод. Начиная с какого-то размера блока число в последней колонки становится сильно меньше — значит размер блока равен оному из предыдущей строки. Этот размер и надо использовать в драйвере block2mtd.
- Лимит блоков
- запускаем, варьируя Y путём деления отрезка пополам flashbench -e 4M --open-au --open-au-nr=Y /dev/sdc. 4M здесь — размер блока, полученный в предыдущем пункте (необязателен, но с ним удобнее). Пока Y <= лимиту блоков, скорость в зависимости от размера записываемого блока падать не будет. Как только Y превысит лимит блоков, скорость сразу начнёт падать в зависимости от размера записываемого блока почти линейно.
[ Хронологический вид ]Комментарии
Войдите, чтобы комментировать.