THP collapse failed write-protection — Тюнинг Transparent HugePages
Архитектура ошибки и симптомы сбоя
Сообщение «transparent_hugepage: collapse failed due to write-protection» генерируется фоновым потоком ядра khugepaged (подсистема Transparent Huge Pages — THP). Ошибка возникает, когда демон khugepaged пытается объединить 512 базовых 4KB-страниц памяти в одну большую 2MB-страницу (HugePage Collapse), но наталкивается на страницы, защищенные от записи (Write-Protected / Copy-on-Write / KSM / Shared Memory). Неудачные попытки вызывают паразитный расход процессорного времени и спайки задержек приложений.
Диагностическая таблица параметров сбоя
| Параметр | Значение | Инженерный смысл сбоя |
|---|---|---|
| khugepaged | Kernel THP Daemon | Ядерный поток сканирования и фонового объединения смежных 4KB страниц в 2MB. |
| Collapse Failure | COW / Write-Protect Block | Невозможность атомарной замены страниц из-за разделяемых блокировок памяти. |
| Impact | Latency Spikes / Redis Stalls | Зависания fork() в Redis/PostgreSQL при создании снимков БД (BGSAVE). |
Пошаговое дерево решений и сценарии траблшутинга
Сценарий 1: Проверка текущего статуса и метрик THP
# Проверка режима THP в ядре:
cat /sys/kernel/mm/transparent_hugepage/enabled
cat /sys/kernel/mm/transparent_hugepage/defrag
# Просмотр статистики неудачных попыток collapse:
cat /sys/kernel/mm/transparent_hugepage/khugepaged/pages_collapsed
grep -E "(thp_collapse_alloc_failed|thp_split_page)" /proc/vmstatСценарий 2: Перевод Transparent HugePages в режим madvise
Режим madvise запрещает автоматическое слияние страниц для всех процессов, разрешая его только тем приложениям, которые явно запросили HugePages (через вызов madvise(MADV_HUGEPAGE)):
# Переключение THP в режим по запросу (рекомендовано для production):
echo madvise | sudo tee /sys/kernel/mm/transparent_hugepage/enabled
echo madvise | sudo tee /sys/kernel/mm/transparent_hugepage/defragСценарий 3: Полное отключение THP для баз данных (Redis, MongoDB, Oracle)
# Отключение THP на лету:
echo never | sudo tee /sys/kernel/mm/transparent_hugepage/enabled
echo never | sudo tee /sys/kernel/mm/transparent_hugepage/defrag
# Закрепление в параметрах загрузчика GRUB (/etc/default/grub):
GRUB_CMDLINE_LINUX="transparent_hugepage=never"
sudo update-grubСценарий 4: Тюнинг параметров сканирования khugepaged
Если THP необходим, уменьшите частоту сканирования демона:
# Увеличение интервала между сканированиями до 60 секунд (60000 ms):
echo 60000 | sudo tee /sys/kernel/mm/transparent_hugepage/khugepaged/scan_sleep_millisecsITSTM выполнит комплексную оптимизацию подсистемы виртуальной памяти ядра, исключит блокировки Copy-on-Write и настроит статические HugeTLB.
Частые вопросы (FAQ)
Почему Redis настоятельно требует отключать Transparent HugePages?
При выполнении команды BGSAVE Redis делает системный вызов fork(). Если включен THP, любое изменение одного ключа заставляет ядро копировать целиком 2MB-страницу вместо 4KB, что мгновенно исчерпывает оперативную память и замораживает транзакции.
Чем Transparent HugePages отличаются от Static HugePages (HugeTLB)?
THP управляется ядром динамически и автоматически (создавая накладные расходы на дефрагментацию и collapse). Static HugePages заранее резервируются при старте ОС через vm.nr_hugepages и не могут быть фрагментированы или вытеснены.
Что делает параметр transparent_hugepage/defrag=never?
Он запрещает процессам переходить в прямое ожидание (Direct Reclaim/Compaction) при нехватке 2MB HugePages, мгновенно отдавая стандартные 4KB страницы и исключая задержки I/O.
Как проверить, сколько THP страниц использует конкретный процесс?
Выполните команду: grep -e AnonHugePages /proc/<PID>/smaps | awk '{sum+=$2} END {print sum " KB"}'.