Linux отключить transparent hugepages

Обновлено: 05.07.2024

Настройка Swappiness, кэширование, оптимизация операций чтения/записи для ускорения работы Ceph, тюнинг Ceph.

Единой конфигурации для идеальной работы нет, оптимизация и настройка производится исходя из требований к различного рода задачам.

В данном примере будет рассмотрен один из вариантов для улучшения работы дисковой подсистемы Ceph.

Все действия в данной статье могут привести к краху системы.

Не выполняйте их на рабочих серверах. Пожалейте нервы :)

1. read_ahead

Параметр read_ahead ускоряет операции дискового чтения путем предварительной выборки и их загрузки в оперативную память. Установка относительно высоких значений read_ahead даст преимущества клиентам при выполнении операций последовательного чтения.

Проверить текущее установленное значение параметра можно командой:

Для установки read_ahead бОльшего значения, используем следующую команду:

Аналогично необходимо изменить read_ahead для всех RBD, помеченных для данного хоста.

Убедитесь, что вы используете правильное имя пути устройства.

2. Отключим синтаксический анализ каталога OSD с помощью updatedb

Утилита под названием updatedb сканирует всю систему и обновляет файл базы данных mlocate.db .

База данный это файл, в котором содержится информация о файлах и их путях в системе Linux.

3. Отключить transparent hugepage(THP)

Проверить статус HugePages можно командой:

Нулевое значение означает, что HugePages отключен в системе.
Ежели это иначе, то следуем дальше.

Для отключения THP при загрузке отредактируем файл grub.conf :

Для отключения THP “на лету” выполним команды:

4. Использование ОЗУ и SWAP

Параметр vm.swappiness по умолчанию имеет значение 60 и контролирует процент свободной памяти, при которой начнется активный сброс страниц в раздел swap.

Значение параметра достаточно легко понять.

100-60 = 40% занятой памяти при которой система уже начнет использовать раздел swap

Лучшим решением будет изменить данный параметр на 10 и указать системе не использоваться swap, пока ОЗУ не достигнет 90%.

Для изменения параметра “на лету” выполним:

Для перманентной настройки параметра, изменим файл /etc/sysctl.conf и добавим строчку:

Параметр vfs_cache_pressure по умолчанию имеет значение 100 и отвечает за уровень выделяемой памяти под кэш.

Увеличение данного параметра заставляет ядро активнее выгружать неиспользуемые страницы памяти из кеша, т.е. количество выделяемой оперативной памяти под кеш будет расти медленнее, что снизит вероятность того, что будет задействован раздел swap.

При уменьшении параметра, ядро, наоборот, будет дольше держать страницы памяти в кеше, в том числе и в swap’е.

Это имеет смысл при небольшом количестве ОЗУ, например, если у нас 512 МБ памяти, то параметр vfs_cache_pressure можно выставить равным 50. Это позволит сократить количество дисковых операций в swap разделе, так как удаление неиспользуемых страниц будет происходить реже.

Дальнейшее уменьшение этого параметра может привести к нехватке памяти.

Если мы хотим ускорить работу системы и у нас достаточно памяти, то изменим значение системы, добавив строчки в файл /etc/sysctl.conf :

Параметр kernel.pid_max служит для поддержки большего значения тредов (threads). В теории, максимум это - 4,194,303.

Внесем изменения в файл /etc/sysctl.conf , добавив строчку:

vm.zone_reclaim_mode

Параметр vm.zone_reclaim_mode . Опасен для файловых серверов.

Важно, чтобы значение было выставлено в ноль.

Оптимизация Ceph OSD

Отключим ведение журнала в памяти.

Каждая подсистема Ceph имеет свой уровень логирования и регистрирует это в памяти.

Мы можем установить разные значения для каждой из этих подсистем, установив уровень логирования и уровень памяти для ведения журнала отладки в диапазоне от 1 до 20. (Где 1 является кратким и 20 - подробным).

Первое значение - это уровень логирования, а второй - уровень памяти. Мы должны отделить их с помощью косой черты (/):

debug <subsystem> = <log-level>/<memory-level>

Логирование по умолчанию идеально подходит для наблюдения за кластером.

Если ведение журнала в памяти влияет на производительность или потребление памяти, в это случае мы можем отключить его.

Чтобы отключить добавьте следующие параметры:

Установим max_open_files для того чтобы задать максимальное значение открытых дескрипторов файлов на уровне ОС:

Для всех SSD-дисков установим настройки:

Текущий конфигурационный файл тестового сервера:

(Будет изменяться в зависимости от проведенных тестов и рекомендаций)

Так что вместо времени выполнения, если я хочу сделать это постоянным изменением, я должен добавить вышеупомянутую строку в /proc/vmstat файл?

Чтобы сделать такие параметры, как этот перманент, вы обычно добавляете их в файл /etc/sysctl.conf . Вы можете увидеть полный список доступных опций с помощью этой команды:

пример

Вы можете посмотреть hugepage в выводе так:

Это не там?

В частности, на этой странице они упоминают, как отключить функцию огромной страницы .

Предпочтительный метод отключения Transparent HugePages - добавить «transparent_hugepage = never» в строку загрузки ядра в файле «/etc/grub.conf».

Сервер должен быть перезагружен, чтобы это вступило в силу.

Или вы можете добавить команду в свой /etc/rc.local файл.

Я думаю, что я выбрал бы второй вариант, так как первый рискует быть сброшенным при переходе с одного ядра на другое.

Вы можете подтвердить, что это сработало с помощью следующей команды после перезагрузки:

Первый вариант можно использовать для обновления ядра, добавив transparent_hugepage = never в параметр GRUB_CMDLINE_LINUX_DEFAULT в / etc / default / grub в большинстве дистрибутивов. Если вывод cat /sys/kernel/mm/transparent_hugepage/enabled равен [always] madvise never , тогда статус always или что он включен (обратите внимание на [] квадратные скобки always ) Не путайте огромные страницы и прозрачные огромные страницы. Последнее может вызвать много проблем, в основном из-за высокой загрузки ЦП при постоянной попытке дефрагментации памяти и преобразования обычных страниц размером 4 КБ в огромные страницы размером 2 МБ. @Rwky - при настройке в соответствии с вашим предложением - я бы выделил следующее действие после сохранения файла - выполнить, sudo update-grub чтобы получить новые настройки, «записанные в камне». +1 за указание строки файла grub. Обновление для тех, кто работает в EC2, cloudimg добавляет файл /etc/default/grub.d/50-cloudimg-settings.cfg, который переопределяет настройки в / etc / default / grub, добавляя файл /etc/default/grub.d/. 99-transparent-огромный page.cfg с содержимым GRUB_CMDLINE_LINUX_DEFAULT = "$ GRUB_CMDLINE_LINUX_DEFAULT transparent_hugepage = never" решит эту проблему.

Я просто хотел добавить к этому вопросу, поскольку я пытался отключить прозрачные огромные страницы в CentOS v6, чтобы включить TokuDB для MariaDB. Я добавил скрипт, упомянутый @slm, /etc/rc.local и он отключил прозрачные огромные страницы. Однако из-за того, как скрипты запуска работают в Linux, /etc/rc.local выполняется после запуска всех сервисов. Поэтому прозрачные огромные страницы были отключены после того, как MariaDB уже был запущен, и движок TokuDB не инициализировался. Единственный другой способ отключить прозрачные огромные страницы - добавить transparent_hugepage=never в параметр ядра.

Я заметил комментарий @ Rwky You can make the first option survive kernel updates by adding transparent_hugepage=never to the GRUB_CMDLINE_LINUX_DEFAULT option in /etc/default/grub on most distributions. и обнаружил, что CentOS не поддерживает /etc/default/grub файл и беспокоился об transparent_hugepage=never исчезновении параметров ядра при его обновлении. Но не волнуйтесь, CentOS настроен на сохранение любых изменений параметров ядра в grub, поэтому при обновлении они сохраняются.

Кроме того, правильный способ изменения параметров ядра для grub - с grubby . Я создал этот простой скрипт для добавления transparent_hugepage=never в каждое ядро grubby :


Ранее я рассказал о том, как проверить и включить использование Hugepages в Linux.
Эта статья будет полезна, только если у вас действительно есть, где использовать Hugepages. Я встречал множество людей, которые обманываются перспективой того, что Hugepages волшебным образом повысят производительность. Тем не менее hugepaging является сложной темой, и при неправильном использовании он способен понизить производительность.

Проблема:
Необходимо проверить, включены ли HugePages в вашей системе.

Решение:
Оно довольно простое:

Вы получите что-то вроде этого:

Вы увидите список доступных опций (always, madvise, never), при этом текущая активная опция будет заключена в скобки (по умолчанию madvise).

madvise означает, что transparent hugepages включены только для областей памяти, которые явно запрашивают hugepages с помощью madvise(2).

always означает, что transparent hugepages включены всегда и для всех процессов. Обычно это повышает производительность, но если у вас есть вариант использования, где множество процессов потребляет небольшое количество памяти, то общая нагрузка на память может резко возрасти.

never означает, что transparent hugepages не будут включаться даже при запросе с помощью madvise. Чтобы узнать больше, обратитесь к документации ядра Linux.

Как изменить значение по умолчанию

Вариант 1: Напрямую изменить sysfs (после перезагрузки параметр вернется к значению по умолчанию):

Вариант 2: Измените системное значение по умолчанию, перекомпилировав ядро с измененной конфигурацией (этот вариант рекомендуется только если вы используете собственное ядро):

  • Чтобы поставить always по умолчанию, используйте:
  • Чтобы поставить madvise по умолчанию, используйте:

Мы попытаемся выборочно объяснить преимущества, недостатки и возможные ошибки при использовании Hugepages. Поскольку технологически сложная и педантичная статья, вероятно, будет тяжелой для понимания людям, которые обманываются считая Hugepages панацеей, я пожертвую точностью в угоду простоты. Просто стоит иметь ввиду, что множество тем действительно сложны и поэтому сильно упрощены.

Обратите внимание, что мы говорим о 64-х разрядных x86 системах, работающих на Linux, и что я просто предполагаю, что система поддерживает transparent hugepages (так как не является недостатком то, что hugepages не подменяются), как это случается практически в любой современной среде Linux.

В ссылках ниже я прикреплю больше технического описания.

Виртуальная память

Если вы программист C++, вы знаете, что у объектов в памяти есть конкретные адреса (значения указателя).

Однако эти адреса необязательно отражают физические адреса в памяти (адреса в ОЗУ). Они представляют собой адреса в виртуальной памяти. Процессор имеет специальный модуль MMU (memory management unit), который помогает ядру сопоставлять виртуальную память с физическим местоположением.

Такой подход имеет множество преимуществ, но самые основные из них:

  • Производительность (по различным причинам);
  • Изоляция программ, то есть ни одна из программ не может читать из памяти другой программы.

Что такое страницы?

Виртуальная память поделена на страницы. Каждая отдельная страница указывает на определенную физическую память, она может указывать на область в оперативной памяти, а может на адрес, назначенный физическому устройству, например видеокарте.

Большинство страниц, с которыми вы имеете дело, указывают либо на ОЗУ, либо подменяются (swap), то есть хранятся на жестком диске или SSD. Ядро управляет физическим расположением каждой страницы. Если осуществляется доступ к подмененной странице, ядро останавливает поток, который пытается получить доступ к памяти, считывает страницу с жесткого диска/SSD в оперативную память, а затем продолжает выполнение потока.

Этот процесс прозрачен для потока, то есть он не обязательно читает напрямую с жесткого диска/SSD. Размер нормальных страниц – 4096 байт. Размер Hugepages – 2 мегабайта.

Буфер ассоциативной трансляции (TLB)

Когда программа обращается к некоторой странице памяти, центральный процессор должен знать, с какой физической страницы считывать данные (то есть иметь виртуальную карту адресов).

В ядре есть структура данных (таблица страниц), которая содержит всю информацию об используемых страницах. С помощью этой структуры данных можно сопоставить виртуальный адрес с физическим адресом.

Однако таблица страниц довольно сложна и работает медленно, поэтому мы просто не можем каждый раз анализировать всю структуру данных, когда какой-либо процесс обращается к памяти.

К счастью в нашем процессоре есть TLB, который кэширует сопоставление виртуальных и физических адресов. Это значит, что несмотря на то, что нам нужно проанализировать таблицу страниц при первой попытке получить доступ, все последующие обращения к странице могут обрабатываться в TLB, что обеспечивает быструю работу.

Поскольку он реализован в качестве физического устройства (что делает его в первую очередь быстрым), его емкость ограничена. Поэтому, если вы захотите получить доступ к большему количеству страниц, TLB не сможет хранить сопоставление для всех них, вследствие чего ваша программа будет работать намного медленнее.

Hugepages приходят на помощь

Итак, что мы можем сделать, чтобы избежать переполнения TLB? (Мы предполагаем, что программе все еще нужен тот же объем памяти).

Вот тут-то и появляются Hugepages. Вместо 4096 байт, требующих всего одну запись в TLB, одна запись в TLB теперь может указывать на колоссальные 2 мегабайта. Будем предполагать, что TLB имеет 512 записей, здесь без Hugepages мы можем сопоставить:

Тогда как с ними мы можем сопоставить:

Именно поэтому Hugepages – это круто. Они могут повысить производительность без значительного приложения усилий. Но здесь есть существенные оговорки.

Подмена Hugepages

Ядро автоматически отслеживает частоту использования каждой страницы памяти. Если физической памяти (ОЗУ) недостаточно, ядро переместит менее важные (реже используемые) страницы на жесткий диск, чтобы освободить часть ОЗУ для более важных страниц.
В принципе, то же самое касается и Hugepages. Однако ядро может менять местами только целые страницы, а не отдельные байты.

Предположим, у нас есть такая программа:

В этом случае ядру нужно будет подменить (прочитать) целых 2 мегабайта информации с жесткого диска/SSD только для того чтобы вы прочитали один байт. Что касается обычных страниц, с жесткого диска/SSD надо прочитать всего 4096 байт.

Поэтому, если hugepage подменяется, ее чтение происходит быстрее, только если вам нужно получить доступ ко всей странице. Это значит, что если вы пытаетесь получить доступ случайным образом к различным частям памяти и просто считываете пару килобайт, вам следует использовать обычные страницы и больше ни о чем не беспокоиться.

С другой стороны, если вам нужно получать доступ к большой части памяти последовательно, hugepages увеличат вашу производительность. Тем не менее, вам нужно проверить это самостоятельно (а не на примере абстрактного ПО) и посмотреть, что будет работать быстрее.

Аллокация в памяти

Если вы пишете на С, вы знаете, что вы можете запросить сколь угодно малые (или почти сколь угодно большие) объемы памяти из кучи с помощью malloc() . Допустим, вам нужно 30 байт памяти:

Программисту может показаться, что вы “запрашиваете” 30 байт памяти из операционной системы и возвращаете указатель на некоторую виртуальную память. Но на самом деле malloc () — это просто функция C, которая вызывает изнутри функции brk и sbrk для запроса или освобождения памяти из операционной системы.

Однако, запрашивать больше и больше памяти для каждой аллокации неэффективно; наиболее вероятно, что какой-либо сегмент памяти уже был освобожден (free()) , и мы можем повторно его использовать. malloc() реализует довольно сложные алгоритмы для повторного использования освобожденной памяти.

При этом для вас все происходит незаметно, так почему это должно вас волновать? А потому, что вызов free() не означает, что память обязательно возвращается сразу же операционной системе.

Существует такое понятие, как фрагментация памяти. В крайних случаях есть сегменты кучи, где используется только несколько байтов, в то время, как все, что находится между ними было освобождено (free()) .

Обратите внимание, что фрагментация памяти является невероятно сложной темой, и даже незначительные изменения в программе могут значительно повлиять на нее. В большинстве случаев программы не вызывают значительной фрагментации памяти, но вы должны иметь ввиду, что если с фрагментацией в некоторой области кучи возникла проблема, hugepages могут только усугубить ситуацию.

Выборочное применение hugepages

После прочтения статьи, вы определили, какие части вашей программы могут извлечь выгоду из применения hugepages, а какие – нет. Так следует ли вообще включать hugepages?

К счастью, вы можете использовать madvise() , чтобы включить hugepaging только для тех областей памяти, где это будет полезно.

Для начала, проверьте, что hugepages работают в режиме madvise(), с помощью инструкции в начале статьи.

Затем, используйте madvise() , чтобы указать ядру, где именно использовать hugepages.

Обратите внимание, что этот метод — просто рекомендации ядру по управлению памятью. Это не означает, что ядро будет автоматически использовать hugepages для заданной памяти.

Обратитесь к документации (manpage) madvise, чтобы узнать больше об управлении памятью и madvise() , у этой темы невероятно крутая кривая обучения. Поэтому, если вы намереваетесь действительно хорошо разобраться в ней, подготовьтесь к чтению и тестированию в течение нескольких недель, прежде чем рассчитывать на хоть какой-то положительный результат.

В этой заметке я расскажу о нескольких параметрах ядра которые очень критичны для нормальной работы Ceph OSD и RGW.

Отключение THP в runtime:

Что бы отключить THP перманентно необходимо добавить к параметрам ядра: transparent_hugepage=never

Еще один параметр ядра который призван повысить эффективность использования памяти. Если у вас в сервере несколько соккетов и соответственно NUMA-узлов то этот механизм скорее всего включен (его то включают то выключают, зависит от ядра). Особенности NUMA в общих чертах описаны тут.

Собственно vm.zone_reclaim_mode=1 призван помочь выделять память процессу в той NUMA в которой он работает в настоящий момент. При этом, если в нужной NUMA памяти недостаточно то ядро может пытаться высвободить нужный объем путем сброса страничного кеша, например. В результате, процесс запрашивающий память может подвисать на мгновения или даже долше. Лично я видел это не один раз на серверах где по различным причинам не был отключен vm.zone_reclaim_mode . Например RGW инстанас может работать совершенно нормально только очень медленно. Обрабатывать не 10-20 реквестов в секунду а 2-3 и с огромными задержками. И такое же было с OSD, они переодически не отвечали на heartbeat и мониторы отмечали их как DOWN. Я долго не мог понять в чем дело. Отключение этого механизма приводит к тому, что ядро не пытается выделить память путем ее высвобождения а выделяет там где есть в том числе и на другой NUMA-ноде. В доке ядра сказано следующее:

For file servers or workloads
that benefit from having their data cached, zone_reclaim_mode should be
left disabled as the caching effect is likely to be more important than
data locality.

То есть, если приложение активно использует страничный кеш то общая производительность может быть лучше даже если кеш будет размазан по разным NUMA. Ceph активно использует страничный кеш, особенно с filestore и по это причине рекомендуется отключать этот механизм (если включен в вашем дистрибутиве):

Я уже писал про эту ошибку ранее.
Тогда мы увеличили резерв до 512 Mb для серверов с 32 Gb и 12 OSD и эти ошибки перестали нас беспокоить. Но в последние несколько месяцев они снова дают о себе знать в моменты высокой нагрузки. Сейчас мы резервируем 2 GB:

Посмотрите логи ядра, если вы периодически видите такие ошибки то и вам нужно увеличивать объем резерва. Мы увеличивали его с шагом в 64 Mb пока не избавлялись от ошибок.

Кстати есть еще один теоретический способ избавиться от этих ошибок путем повышения значения: vm.vfs_cache_pressure=100 . Если повышать значение, то в теории страничный кеш будет высвобождаться агрессивнее и проблемы с недостатком памяти и ошибок page allocation failure быть не должно. Но лично мне не удалось подобрать правильное значение. Даже при vm.vfs_cache_pressure=2000 ошибки продолжали напоминать о себе и в итоге ситуация разрешилась путем увеличения резерва.

Опять же, ошибка page allocation failure частично возникает не из-за недостатка памяти а из-за ее сильной фрагментации. Это особенно характерно для нагруженных OSD-серверов.
Оценить уровень фрагментации:

Если у вас много страниц в первых нескольких колонках а в остальных не густо то у вас тоже есть проблема фрагментации памяти. С помощью следующей команды по cron можно немного исправлять ситуацию:

Я не знаю как это работает, честно. Но после выполнения этой команды память немного перераспределяется и появляются в том числе и большие линейные куски памяти. Распределение памяти из dmesq приведенное выше как раз получено на системе с такой задачей в cron.

Параметры и настройки ядра относящиеся к подсистеме памяти помогающие Ceph работать стабильно и с оптимальной производительностью:

Читайте также: