Некоторое время назад я рассказывал об установке SSD-накопителя серии Samsung 840 EVO вместо штатного в iMac, а также о настройке Linux для эффективной работы с таким накопителем. Сразу же после замены можно наслаждаться исключительной отзывчивостью системы и мгновенным запуском программ. И всё это по цене, наконец-то ставшей относительно доступной.
Но, как водится, счастье долгим не бывает, и осенью 2014 года в прессе много писали (статья на Extremetech, пост на Гиктаймс) о технологическом дефекте, проявлявшемся в постепенном снижении скорости чтения файлов, записанных какое-то время назад. Проблема вызывается «уплыванием» напряжений, выдаваемых ячейками памяти, за пределы нормы, что заставляет контроллер накопителя осуществлять многократные попытки чтения, а это, в свою очередь, выливается в значительное снижение скорости чтения. Причём, чем больше времени прошло с момента записи файла, тем сильнее «уплывают» рабочие уровни ячеек и тем ниже становится скорость чтения этого файла.
По моим измерениям, за 10 месяцев (диск я заменил в августе прошлого года) скорость упала с 280 МБ/с до примерно 30 МБ/с, то есть на целый порядок! «Непорядок», — подумал я.
Ну а что же Самсунг? Компания сначала активно отрицала наличие проблемы, но потом сдалась и выпустила несколько обновлений для её решения. Однако, как выяснилось чуть позже, ни одно из них не устраняло проблему окончательно. В итоге они представили версию драйвера, периодически просто перезаписывающего данные на диске, и успокоились. Загвоздка в том, что драйвер доступен лишь для Windows и Mac OS, а о Linux, как обычно, забыли.
Меня десятикратное падение скорости чтения как-то не радовало, и решение созрело довольно быстро. Нужна утилита, способная перезаписывать файл прямо на диске, теми же самыми данными. Тогда её можно будет периодически, раз в пару месяцев, напускать на раздел с Линуксом (в Линуксе раздел — это ведь тоже файл).
Программа rewrite-inplace
Итак, имею честь представить эту бесхитростную программу: rewrite-inplace. Написана она на простом сермяжном C, и компилируется командой:
gcc rewrite-inplace.c -o rewrite-inplace
Что создаст исполняемый файл rewrite-inplace
в текущем каталоге. Программа принимает имя файла в качестве аргумента командной строки. В процессе работы она периодически выводит счётчик перезаписанных байт; её можно также безопасно прервать нажатием Ctrl+C (поскольку данные никуда не перемещаются, сделать это можно в любой момент).
Программа использует низкоуровневые функции ввода/вывода, без буферизации, которая в данном случае скорее вредна, чем полезна.
Инструкция
В целом рекомендуемый мной процесс восстановления скорости чтения таков:
Самое важное: создать резервные копии всего, располагающегося на обрабатываемых разделах и имеющего какую-либо ценность.
Я не принимаю никаких претензий по поводу смерти вашего любимого файла/диска/кота в результате использования данной программы.
Загрузиться с какого-нибудь live-дистрибутива Linux (например, Ubuntu). Важно: я использовал программу лишь с 64-битной версией системы, не поручусь за работоспособность на 32-битной.
Отключить скринсейвер, блокировку экрана, остановку дисков по времени и т.п.
Скомпилировать программу на запущенной системе (её библиотеки могут отличаться от библиотек основной ОС):
gcc rewrite-inplace.c -o rewrite-inplace
Запустить GParted, чтобы выяснить имена разделов обрабатываемого диска. Крайне важно: разделы должны быть отмонтированными, проверить можно по их отсутствию в выводе команды
mount
.Запустить программу для каждого обрабатываемого раздела из-под
root
, например:sudo rewrite-inplace /dev/sda1 # Это просто пример!
Ждать завершения работы программы
и молиться. По окончании проверить целостность раздела командой:sudo fsck -f /dev/sda<раздел>
Мои результаты
На перезапись 900-гигабайтного раздела с ext4 программа затратила около трёх с половиной часов; по счётчику байтов было хорошо заметно, что к концу процесс стал значительно быстрее (логично, что самые старые файлы располагаются в начале).
Итог: скорость чтения полностью восстановилась:
$ dd if=/very/old/file of=/dev/null bs=10M
97+1 records in
97+1 records out
1020327050 bytes (1.0 GB) copied, 3.62436 s, 282 MB/s
$ dd if=/another/old/file of=/dev/null bs=10M
95+1 records in
95+1 records out
1000000000 bytes (1.0 GB) copied, 3.56764 s, 280 MB/s
$ dd if=/new/file of=/dev/null bs=10M
1528+1 records in
1528+1 records out
16028794368 bytes (16 GB) copied, 56.9275 s, 282 MB/s
Дисклеймер
Автор не даёт никаких гарантий, вы используете программу НА СВОЙ СТРАХ И РИСК! ■
Комментарии