Добавить в корзинуПозвонить
Найти в Дзене
IT Еxtra

«grep -r» убивает ваш NVMe быстрее компиляции ядра. Вот почему

Вы думаете, что компиляция ядра убивает SSD. Нет. Компиляция — это предсказуемая последовательная запись. Контроллер её любит. А вот любимая вами же команда grep -r по директории с миллионом мелких файлов — это чтение на миллиард микроопераций, которое превращает ваш быстрый NVMe в разогретую сковородку, разгоняя параметр Wear_Leveling_Count быстрее, чем циклическая перезапись диска торрентами. Почему так происходит — читайте под катом. Давайте внесём ясность. Да, циклы записи-стирания (P/E) для NAND-памяти ограничены — от 100–1000 циклов для QLC-дисков до 3000 для TLC и 10 000 для MLC. Чтение само по себе ячейку не убивает. Но вот в чём подвох: когда вы запускаете grep -r, система не просто «читает» файлы. Происходит то, что инженеры называют write amplification — скрытый множитель записи, который превращает ваше безобидное чтение в настоящую бойню. Механизм простой: когда grep читает файл, ОС загружает его в page cache (оперативную память). Если памяти много, а vm.dirty_ratio настрое
Оглавление

Вы думаете, что компиляция ядра убивает SSD. Нет. Компиляция — это предсказуемая последовательная запись. Контроллер её любит. А вот любимая вами же команда grep -r по директории с миллионом мелких файлов — это чтение на миллиард микроопераций, которое превращает ваш быстрый NVMe в разогретую сковородку, разгоняя параметр Wear_Leveling_Count быстрее, чем циклическая перезапись диска торрентами.

https://clck.ru/3Tv8ny
https://clck.ru/3Tv8ny

Почему так происходит — читайте под катом.

Чтение ≠ чтению

Давайте внесём ясность. Да, циклы записи-стирания (P/E) для NAND-памяти ограничены — от 100–1000 циклов для QLC-дисков до 3000 для TLC и 10 000 для MLC. Чтение само по себе ячейку не убивает. Но вот в чём подвох: когда вы запускаете grep -r, система не просто «читает» файлы. Происходит то, что инженеры называют write amplification — скрытый множитель записи, который превращает ваше безобидное чтение в настоящую бойню.

Механизм простой: когда grep читает файл, ОС загружает его в page cache (оперативную память). Если памяти много, а vm.dirty_ratio настроен агрессивно (по умолчанию часто 20%), Linux копит изменения в кэше и сбрасывает их на диск огромными пачками. Во время этого сброса контроллер SSD вынужден перекладывать данные из одних блоков в другие, делать garbage collection и применять wear leveling. Всё это — дополнительные фоновые записи, которых не было бы, если бы вы просто запустили компиляцию ядра (которая пишет последовательно и предсказуемо).

То есть вы читаете 1 ГБ логов, а SSD в ответ на это может перезаписать 2–4 ГБ собственных служебных данных. И причём здесь grep? При том, что он заставляет систему читать РАЗНОРОДНЫЕ данные. Мелкие файлы, случайный доступ, постоянное переключение контекста — это кошмар для контроллера.

Цифры и примеры из жизни

Люди на форумах уже сталкивались с этим. Например, пользователь TrueNAS обнаружил, что его пара Samsung EVO 870 «износилась» до 49% за шесть месяцев при использовании в пуле приложений. Причина — не запись видео 24/7, а постоянный мелкий I/O от работающих приложений. Похожим страдает и grep при рекурсивном обходе директорий.

Один исследователь прогонял 646 запросов locate (аналог grep по базе файлов) через SSD Samsung 840. Только эти 646 запросов вызвали заметный износ, хотя на HDD он бы даже не заметил нагрузки.

Альтернативная реализация grep под названием grab показывает ускорение до 8 раз на SSD именно за счёт параллельного чтения и оптимизации работы с памятью. Ускорение достигается не магией, а тем, что grab сокращает количество лишних операций ввода-вывода, тем самым уменьшая write amplification. То есть разработчики знают о проблеме и пытаются её лечить.

Дьявол в мелочах

Особенно опасен grep -r в двух сценариях:

  1. На почти заполненном диске. Когда на SSD остаётся меньше 15–20% свободного места, контроллеру становится негде маневрировать. Алгоритмы выравнивания износа и garbage collection работают в разы менее эффективно. Любое чтение провоцирует каскад перезаписей.
  2. На директориях с сотнями тысяч мелких логов или исходников. Каждый маленький файл — это отдельный вызов, отдельная аллокация в page cache, отдельный потенциальный триггер для сброса dirty-страниц.

А что делать? Убить grep? Нет. Настроить систему.

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

  1. Настройте vm.dirty_ratio. Для SSD-накопителей рекомендуется снижать этот параметр до 5–15% вместо стандартных 20. Это заставит систему сбрасывать данные на диск чаще, но меньшими порциями, снижая нагрузку пиковой записи. Для серверных сборок с NVMe иногда советуют вообще выставлять vm.dirty_ratio=5 и vm.dirty_background_ratio=3.
  2. Используйте индексацию. Утилита ugrep с плагином ugrep-indexer создаёт индекс содержимого файлов и при повторных поисках не сканирует всё подряд, а только потенциально релевантные файлы, ускоряя работу вплоть до 20 раз и кардинально снижая I/O.
  3. Откажитесь от -r там, где можно обойтись find ... -exec с фильтрацией по типам файлов. Это позволит исключить бинарники и временные файлы.
  4. Перенесите журнал файловой системы (ext4 journal) на HDD. Если в системе есть жёсткий диск, вы можете вынести туда журнал, сохранив все преимущества журналирования, но без износа SSD. Делается это через mke2fs -O journal_dev /dev/hdd_device и монтирование.
  5. Регулярно выполняйте TRIM. Команда fstrim -av позволяет ОС сообщить SSD, какие блоки действительно свободны, снижая write amplification.

Итог

Компиляция ядра убивает ваш SSD? Нет. Она пишет последовательно и предсказуемо — контроллер SSD оптимизирует это легко. А вот сотня grep -r в день по случайным директориям с миллионом мелких файлов, вкупе с плохими настройками кэширования и заполненным диском, способна отправить ваш NVMe в мусорку за год-два.

Не верьте мифам. Grep не «читает» — он провоцирует запись.

Берегите свои SSD. И не забывайте про vm.dirty_ratio.