Huge Pages в PostgreSQL

    У PostgreSQL починаючи з версії 9.4 з'явилася підтримка великих сторінок. Це дуже хороша новина, з великими сторінками я познайомився коли працював з віртуалізацією. Коротко про що ж мова. В ОС Linux робота з пам'яттю грунтується на зверненні до сторінок розмір яких дорівнює 4kB (насправді залежить від платформи, перевірити можна через getconf PAGE_SIZE ), так от коли обсяг пам'яті перевалює за кілька десткая, а то й сотні гігабайт управляти нею стає складніше, збільшуються накладні витрати на адресацію пам'яті і підтримку сторінкових таблиць. Для полегшення життя і були придумані великі сторінки, розмір яких може бути 2MB а то і 1GB. За рахунок використання великих сторінок можна отримати відчутний приріст швидкості роботи і збільшення чуйності в додатках які активно працюють з пам'яттю. Як я вже зазначив, вперше я зіткнувся з великими сторінками при роботі з віртуалізацією, зокрема з KVM. Проведені в свій час тести показали що приріст продуктивності віртуальних машин склав від 7 до 10% (вимірювалося все це справа синтетичними тестами різних сервісів типу redis / memcache / postgres / etc всередині віртуальних машин). Тепер це з'явилося в PostgreSQL.
 image
 
Отже повернемося до теми статті, до підтримки великих сторінок в PostgreSQL. Якщо чесно, я давно цього чекав. Вобще запустити PostgreSQL з підтримкою великих сторінок можна було і раніше, за допомогою libhugetlbfs . Однак тепер є вбудована підтримка. Отже нижче опис процесу як налаштувати і запустити PostgreSQL з підтримкою великих сторінок.
 
Для початку слід переконатися що ядро ​​підтримує великі сторінки. Перевіряємо конфіг ядра на предмет наявності опцій CONFIG_HUGETLBFS і CONFIG_HUGETLB_PAGE.
 
# grep HUGETLB /boot/config-$(uname -r)
CONFIG_CGROUP_HUGETLB=y
CONFIG_HUGETLBFS=y
CONFIG_HUGETLB_PAGE=y

У разі відсутності цих опцій, нічого не заробить і ядро ​​слід пересобрать (актуально для Gentoo наприклад).
Очевидно що нам знадобиться PostgreSQL версії 9.4. Установку пакетів і ініціалізацію кластера залишаю за кадром, т.к. залежно від дистрибутива спосіб буде відрізнятися. Переходимо відразу до файлу конфігурації postgresql.conf. За підтримку великих сторінок відповідає параметр huge_page який може приймати три значення, off — не використовувати великі сторінки, on — використовувати великі сторінки, try — спробувати використовувати великі сторінки і в разі недоступності відкотитися на використання звичайних сторінок. Значення try використовується за замовчуванням і є безпечним варіантом. У разі on, сервіс не запуститься якщо великі сторінки не визначені в системі (або їх недостатньо). У разі запуску можна отримати таку помилку:
FATAL: could not map anonymous shared memory: Cannot allocate memory
HINT: This error usually means that PostgreSQL's request for a shared memory segment exceeded available memory, swap space or huge pages. To reduce the request size (currently 148324352 bytes), reduce PostgreSQL's shared memory usage, perhaps by reducing shared_buffers or max_connections.
 
Отже, правимо postgresql.conf (мій postgresql.conf розташовується в місці стандартному для RHEL-based дистрибутивів)
 
# vi /var/lib/pgsql/9.4/data/postgresql.conf
huge_page = try

Тепер включаємо підтримку великих сторінок в системі, по-замовчуванням вони не задіяні. Розрахунок сторінок приблизний і тут слід спиратися на те скільки пам'яті ви готові виділити під потреби СУБД. Зазначу що значення вимірюється в сторінках розміром 2Mb, якщо ви хочете виділити 16GB, то це буде 8000 сторінок.
Офіційна документація пропонує спиратися на значення VmPeak з status файлу який розміщений в / proc / PID / директорії який відповідає номеру процесу postmaster. VmPeak як випливає з назви це пікове значення використання віртуальної пам'яті. Цей варіант дозволяє визначити мінімальну планку від якої слід відштовхуватися, але на мій вдивися такий спосіб визначення теж носить випадковий характер.
 
# head -1 /var/lib/pgsql/9.4/data/postmaster.pid
3076
# grep ^VmPeak /proc/3076/status
VmPeak:  4742563 kB
# echo $((4742563 / 2048 + 1))
2316
# echo 'vm.nr_hugepages = 2316' >> /etc/sysctl.d/30-postgresql.conf
# sysctl -p --system

Переходимо до запуску PostgreSQL. Залежно від системи ініціалізації спосіб запуску може відрізнятися, у мене модний-молодіжний systemd.
 
# systemctl start postgresql-9.4.service

Утилізацію великих сторінок можна подивитися тут.
 
# grep ^HugePages /proc/meminfo
HugePages_Total:    2316
HugePages_Free:     2301
HugePages_Rsvd:      128
HugePages_Surp:        0

На цьому власне все, можна переходити до бенчмарк вашими конкретними workloads. Спасибі за увагу!
    
Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.