В PostgreSQL начиная с версии 9.4 появилась поддержка больших страниц. Это очень хорошая новость, с большими страницами я познакомился когда работал с виртуализацией. Коротко о чем же речь. В ОС Linux работа с памятью основывается на обращении к страницам размер которых равен 4kB (на самом деле зависит от платформы, проверить можно через getconf PAGE_SIZE), так вот когда объем памяти переваливает за несколько десятков, а то и сотни гигабайт управлять ею становится сложнее, увеличиваются накладные расходы на адресацию памяти и поддержание страничных таблиц. Для облегчения жизни и были придуманы большие страницы, размер которых может быть 2MB а то и 1GB. За счет использования больших страниц можно получить ощутимый прирост скорости работы и увеличение отзывчивости в приложениях которые активно работают с памятью. Как я уже отметил, впервые я столкнулся с большими страницами при работе с виртуализацией, в частности с KVM. Проведенные в свое время тесты показали что прирост производительности виртуальных машин составил от 7 до 10% (измерялось все это дело синтетическими тестами различных сервисов типа redis/memcache/postgres/etc внутри виртуальных машин). Теперь это появилось в PostgreSQL.
Итак вернемся к теме статьи, к поддержке больших страниц в PostgreSQL. Если честно, я давно этого ждал. Вобще запустить PostgreSQL с поддержкой больших страниц можно было и раньше, с помощью libhugetlbfs. Однако теперь есть встроенная поддержка. Итак ниже описание процесса как настроить и запустить PostgreSQL с поддержкой больших страниц.
Для начала следует убедиться что ядро поддерживает большие страницы. Проверяем конфиг ядра на предмет наличия опций CONFIG_HUGETLBFS и CONFIG_HUGETLB_PAGE.
В случае отсутствия этих опций, ничего не заработает и ядро следует пересобрать (актуально для 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 дистрибутивов):
Теперь включаем поддержку больших страниц в системе, по-умолчанию они не задействованы. Расчет страниц приблизительный и здесь следует опираться на то сколько памяти вы готовы выделить под нужды СУБД. Отмечу что значение измеряется в страницах размером 2Mb, если вы хотите выделить 16GB, то это будет 8000 страниц.
Официальная документация предлагает опираться на значение VmPeak из status файла который размещен в /proc/PID/ директории который соответствует номеру процесса postmaster. VmPeak как следует из названия это пиковое значение использования виртуальной памяти. Этот вариант позволяет определить минимальную планку от которой следует отталкиваться, но на мой вгляд такой способ определения тоже носит случайный характер.
Переходим к запуску PostgreSQL. В зависимости от системы инициализации способ запуска может отличаться, у меня модный-молодежный systemd.
Утилизацию больших страниц можно посмотреть здесь.
На этом собственно все, можно переходить к бенчмаркам вашими конкретными workloads. Спасибо за внимание!
Итак вернемся к теме статьи, к поддержке больших страниц в 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. Спасибо за внимание!