ZIM-НИЙ SAAALEЗимние скидки: до −50% на старт и −20% на продление
до 31.01.2026 Подробнее
Выберите продукт

HugePages и THP на VDS: когда включать для PHP/БД и как правильно настраивать

Transparent Huge Pages и классические HugePages — мощные, но капризные инструменты. В статье — практические рекомендации для VDS: когда THP отключать, где явные HugePages дают прирост, как рассчитать объём для PHP, MySQL и PostgreSQL и включить без просадок.
HugePages и THP на VDS: когда включать для PHP/БД и как правильно настраивать

С HugePages и THP у админов традиционно два вопроса: включать или выключать, и для кого именно. На VDS ошибки настройки быстро превращаются в хвост латентности и резкие провалы производительности. Разберёмся, чем отличаются классические HugePages от Transparent Huge Pages, когда они полезны для PHP и СУБД (MySQL/MariaDB, PostgreSQL), как посчитать объём, включить без боли и проверить результат.

Что такое HugePages и чем они отличаются от THP

Классические HugePages (hugetlb) — это заранее зарезервированные страницы памяти увеличенного размера, чаще всего 2 МБ (реже 1 ГБ при соответствующей настройке ядра). Они не свопятся и выделяются из отдельного пула, который вы настраиваете через vm.nr_hugepages. Приложение явно просит такие страницы (через MAP_HUGETLB) — поэтому выигрыш предсказуем, а накладные расходы на раздувание/дефрагментацию отсутствуют.

Transparent Huge Pages (THP) — прозрачный механизм ядра, который пытается сам подменять обычные 4 КБ страницы на большие (2 МБ), чтобы снизить TLB-миссы, не требуя от приложения изменений. Красиво на бумаге, но у THP есть цена: фоновая и иногда синхронная дефрагментация памяти, из-за чего у латентно-чувствительных нагрузок возникают «пилы» и случайные задержки. Условно: THP удобно «включил и забыл», но для баз данных так делать нельзя.

Правило большого пальца: СУБД не любят THP. Для них — THP «never» и по возможности явные HugePages. Для PHP — THP «madvise» или «never», а вот для OPcache/JIT полезны именно явные HugePages.

Когда включать и что именно: PHP, MySQL/MariaDB, PostgreSQL

PHP (PHP-FPM, OPcache, JIT)

У PHP два сценария:

  • OPcache: директива opcache.huge_code_pages=1 просит у ядра явные HugePages. Это даёт стабильный выигрыш на больших проектах с тёплым кешем. Требуются зарезервированные 2 МБ-страницы.
  • JIT (PHP 8+): JIT-буфер также может жить в больших страницах. Смысл тот же: меньше TLB-миссов, более предсказуемая производительность.

THP для обычной памяти PHP может быть и полезен, и вреден — всё зависит от шаблона аллокаций и нагрузок. Безопасный компромисс — режим madvise (приложения смогут просить THP через madvise()), а если вы боретесь за минимальную латентность p95/p99 — ставьте never.

MySQL/MariaDB

Рекомендация индустрии много лет неизменна: отключайте THP (never). Для InnoDB имеет смысл пробовать явные HugePages, включив innodb_use_large_pages и заранее зарезервировав нужное количество страниц. Важный нюанс — размер innodb_buffer_pool_size должен быть кратен 2 МБ, иначе часть пула уйдёт в обычные страницы, что сведёт пользу на нет.

Если вы параллельно отстраиваете отказоустойчивость, пригодится материал про настройку GTID и semi-sync фейловера MySQL — посмотрите Гайд по GTID и semi-sync фейловеру. А для стратегии восстановления до точки во времени есть практикум по binlog/GTID — PITR на MySQL/MariaDB.

PostgreSQL

PostgreSQL поддерживает явные HugePages для сегмента общей памяти (shared memory). Включается параметром huge_pages в postgresql.conf (значения try или on). THP — отключить (never): иначе возможны стоп-миры на дефрагментации и скачки задержек при вакууме или интенсивной буферизации.

Проверка текущего состояния THP и HugePages

Быстрые команды для диагностики:

cat /sys/kernel/mm/transparent_hugepage/enabled
cat /sys/kernel/mm/transparent_hugepage/defrag
cat /proc/meminfo | egrep "Huge|AnonHuge"

Ищем, активен ли THP (квадратные скобки вокруг текущего режима), есть ли выделенные HugePages_Total и сколько из них свободно (HugePages_Free). Если AnonHugePages велик, THP активно склеивает память.

Отключаем THP корректно

Разово до перезагрузки:

echo never | sudo tee /sys/kernel/mm/transparent_hugepage/enabled
echo never | sudo tee /sys/kernel/mm/transparent_hugepage/defrag

Постоянно через systemd-юнит (надёжнее, чем редактировать init-скрипты дистрибутива):

sudo tee /etc/systemd/system/disable-thp.service > /dev/null << 'EOF'
[Unit]
Description=Disable Transparent Huge Pages
After=multi-user.target

[Service]
Type=oneshot
ExecStart=/usr/bin/bash -c 'echo never > /sys/kernel/mm/transparent_hugepage/enabled'
ExecStart=/usr/bin/bash -c 'echo never > /sys/kernel/mm/transparent_hugepage/defrag'
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable --now disable-thp.service

Проверьте, что после перезагрузки режим сохранится.

Юнит systemd для отключения THP и проверка статуса

Резервируем явные HugePages (2 МБ) для PHP/БД

Классический путь — настроить vm.nr_hugepages. Сначала оцените, кому и сколько нужно:

  • PHP OPcache: примерно opcache.memory_consumption + opcache.jit_buffer_size (если JIT включён), округлить вверх до 2 МБ-шагов.
  • PostgreSQL: ориентируйтесь на объём общей памяти, которую хотите помещать в большие страницы. Обычно это shared_buffers (целиком) и иногда дополнительные сегменты, если используете расширения.
  • MySQL/MariaDB: целевой объём — innodb_buffer_pool_size (или его значительная часть). Кратно 2 МБ.

Формула для количества страниц: ceil(Нужные_байты / 2097152). Пример: для 2 ГБ нужно ceil(2147483648 / 2097152) = 1024 страницы.

Задаём число страниц и фиксируем конфигом:

echo 'vm.nr_hugepages=1024' | sudo tee /etc/sysctl.d/60-hugepages.conf
sudo sysctl --system
cat /proc/meminfo | egrep "HugePages_Total|HugePages_Free|Hugepagesize"

Если HugePages_Total меньше ожидаемого, ядру не удалось выделить запрошенный объём (фрагментация). Увеличьте число постепенно или перезагрузитесь, затем примените настройку как можно раньше в загрузке. Помните: явные HugePages не свопятся — не резервируйте их «впритык», оставляйте запас под остальную память ОС и приложений.

Схема расчёта и резервирования HugePages под MySQL и PostgreSQL

PHP: включаем OPcache на HugePages

Добавьте в конфигурацию PHP (например, /etc/php.d/10-opcache.ini или профиль для используемой версии):

opcache.enable=1
opcache.enable_cli=0
opcache.memory_consumption=256
opcache.jit_buffer_size=64M
opcache.huge_code_pages=1

Перезапустите пул PHP-FPM и проверьте статус OPcache. При достаточном количестве HugePages ошибки в логах отсутствуют, а общее потребление OPcache укладывается в 2 МБ-кванты. Для косвенной проверки загляните в /proc/<pid_php-fpm>/smaps — сегменты, выделенные на hugetlb, будут видны, или используйте вывод php -i на предмет включённого opcache.huge_code_pages.

PostgreSQL: huge_pages и расчёт

В postgresql.conf включите:

huge_pages = on
shared_buffers = 4GB

Далее посчитайте страницы: 4 ГБ / 2 МБ = 2048. Добавьте запас (например, +5–10%), чтобы избежать ошибок старта при небольшой фрагментации, и выставьте в vm.nr_hugepages. После рестарта Postgres в журнале появится сообщение о использовании huge pages. Если страниц недостаточно, Postgres не стартует или вернётся к обычным страницам (при huge_pages=try), что легко упустить — держите on, когда уверены в расчёте, чтобы не получить «ложно зелёный» запуск.

MySQL/MariaDB: innodb_use_large_pages

В my.cnf включите:

[mysqld]
innodb_buffer_pool_size=8G
innodb_use_large_pages=ON

8 ГБ соответствуют 4096 страницам по 2 МБ. Зарезервируйте их через vm.nr_hugepages=4096 с запасом. Если страниц меньше, InnoDB либо частично уйдёт в обычные страницы, либо отрапортует в логах, что большие страницы недоступны. Следите, чтобы размер буфера был кратен 2 МБ.

THP: режим madvise vs never

Для веб-узлов с упором на PHP и кеши без строгих SLO по задержкам можно рассмотреть madvise. Так приложения, которые умеют просить THP, получат его, а ядро не будет агрессивно дефрагментировать память. Для баз данных и смешанных узлов с высокой нагрузкой по I/O и блокировкам — never.

Проверяйте также параметр дефрагментации THP — он должен быть в «never», иначе даже при madvise можно поймать синхронную дефрагментацию:

cat /sys/kernel/mm/transparent_hugepage/defrag
# ожидаем [never]

Виртуализация и VDS: есть ли подвох

На уровне гипервизора провайдер может использовать свои huge pages. Это прозрачно для гостя: внутри VDS вы настраиваете THP и явные HugePages независимо. Главное — адекватно оценивать доступную RAM. Резерв под hugetlb в госте «вырезает» память из общего пула, поэтому мониторинг свободной памяти и свопа обязателен.

FastFox VDS
Облачный VDS-сервер в России
Аренда виртуальных серверов с моментальным развертыванием инфраструктуры от 195₽ / мес

Проверка и диагностика

  • /proc/meminfo: следите за HugePages_Total, HugePages_Free, HugePages_Rsvd.
  • Логи СУБД: при старте MySQL/MariaDB и Postgres обычно пишут, удалось ли задействовать huge pages.
  • Метрики латентности: сравните p95/p99 до и после. Часто именно хвост задержек — главный выигрыш, а не среднее.
  • Ошибки «Cannot allocate memory»: увеличьте vm.nr_hugepages или уменьшите размер буферов.

Частые ошибки и как их избегать

  • Забыли отключить THP для баз данных. Симптомы: случайные подвисания, рост времени чекпоинтов/вакуума, нестабильный p99.
  • Недорезервировали страницы: OPcache/JIT или InnoDB не смогли занять huge pages и молча откатились.
  • Выделили слишком много: системе не хватает RAM под остальное, начинается давление памяти и swapping у других процессов.
  • Некратные объёмы: буферы не кратны 2 МБ — часть уйдёт в обычные страницы, эффект размывается.
  • Непоследовательность после перезагрузки: забытый unit/конфиг — и THP снова «always».

Мини-чеклист перед внедрением

  1. Зафиксируйте цель: снизить p95/p99 на PHP или стабилизировать СУБД.
  2. Отключите THP: never для БД, madvise или never для PHP-узлов с жёсткими SLO.
  3. Рассчитайте и зарезервируйте vm.nr_hugepages с запасом.
  4. Включите: opcache.huge_code_pages=1, huge_pages=on в Postgres, innodb_use_large_pages=ON в MySQL/MariaDB.
  5. Перезапустите сервисы, проверьте логи и метрики.
  6. Измерьте до/после и оставьте документацию в репозитории/вики проекта.

Итоги

THP — удобный, но непредсказуемый помощник, полезный разве что в режиме madvise на веб-узлах без жёстких SLO. Для СУБД — уверенное «нет». Настоящую пользу приносят явные HugePages: OPcache и JIT у PHP выигрывают стабильно, а InnoDB и PostgreSQL получают предсказуемую производительность без скачков из-за дефрагментации. Ключ к успеху — корректный расчёт, аккуратное резервирование страниц и дисциплина при сопровождении (контроль после перезагрузок, проверка логов и регулярные ревизии объёмов по мере роста данных).

Поделиться статьей

Вам будет интересно

HTTP‑лимиты в Nginx: client_max_body_size и тело запроса для PHP и API OpenAI Статья написана AI (GPT 5)

HTTP‑лимиты в Nginx: client_max_body_size и тело запроса для PHP и API

Почему Nginx внезапно отвечает 413, 400 или зависает на загрузке файлов? Часто причина в лимитах тела HTTP‑запроса: client_max_bod ...
Лимиты ресурсов на VDS: ulimit, sysctl и настройка для веб‑проектов OpenAI Статья написана AI (GPT 5)

Лимиты ресурсов на VDS: ulimit, sysctl и настройка для веб‑проектов

На новом VDS всё обычно летает, пока сайт не вырастет и не упрётся в скрытые лимиты: открытые файлы, процессы, сокеты, память. Раз ...
PHP uploads: настройка загрузки файлов и медиа на Nginx и Apache OpenAI Статья написана AI (GPT 5)

PHP uploads: настройка загрузки файлов и медиа на Nginx и Apache

Разбираем, как в PHP устроена загрузка файлов: временные файлы, лимиты размера и времени, ключевые параметры в php.ini, влияние на ...