CMS Битрикс часто устанавливают с помощью BitrixVM — решения, предоставляемого вендором. Мы подготовили несколько сред для Битрикс, опираясь на рекомендуемые компанией 1C-Битрикс настройки, и провели тестирование производительности. В статье поделимся итогами и разберемся, как настройки веб-сервера, конфигурация PHP и частота процессора влияют на синтетическую производительность сайта на Bitrix.
Базовая настройка PHP
Начнём с настройки PHP. Она включает в себя установку совместимой версии PHP и расширений для них. Для Bitrix также рекомендуется выставить следующие параметры:
max_execution_time = 120Максимальное ограничение времени выполнения скрипта. Многие CMS рекомендуют выставлять значение в 60 секунд. Настройки Bitrix рекомендует выставлять 120 секунд — этого должно быть достаточно для выполнения даже длительных скриптов. Если не хватает даже двух минут, обратите внимание на работу скрипта — возможно, он зависает, либо не хватает других ресурсов. Недостаток времени выполнения скрипта обычно сопровождается сообщением Maximum execution time of N second exceeded
max_input_vars = 10000Ограничение максимального количества входных переменных, которые обрабатывает скрипт. Это ограничение касается всех переменных переданных в скрипт, так что для очень больших приложений может потребоваться большое значение, — например, если производится работа с таблицами или формами со множеством полей. Со стороны приложения может проявляться как пропуск входных данных, а в логах сопровождается сообщением Input variables exceeded N.
memory_limit = 512MОграничение максимального потребления памяти скриптом. Рекомендуется в условиях хостинга, чтобы всем скриптам на сервере хватало памяти. При достижении указанного ограничения скрипт будет завершен. Для разных версий PHP может потребоваться разный объем памяти для приложений. Обновление версии PHP для приложения может потребовать увеличить этот лимит.
В логах сопровождается сообщением Fatal error: Allowed memory size of N bytes exhausted (tried to allocate M bytes). Если оно возникает регулярно, следует изучить участки приложения, в которых возникает исключение: возможно, что проблема заключается не в нехватке памяти для обработки данных, а в логике приложения.
post_max_size = 64M, upload_max_filesize = 64MУвеличиваем размер POST-запроса и максимальный размер загружаемого файла для PHP. Эти настройки позволяют скриптам работать с загружаемыми данными, ограничивая размер загружаемых файлов и POST-запросов. 64 МБайт – достаточное значение для очень большого количества форматов данных. Недостаток значения может сопровождаться пропуском данных, получаемых приложением. Также могут возникать ошибки загрузки файлов в случае, если upload_max_filesize меньше, чем post_max_size.
pcre.jit = 0Отключает компиляцию регулярных выражений перед их сопоставлением. Управляет включением/выключением компиляции регулярных выражений перед выполнением обработки текста. Bitrix рекомендует выключить эту опцию, что может сократить время работы, если часто используются небольшие регулярные выражения на небольших же объемах текста (например, в нескольких строках).
Настройка PHP для Zend OPcache
Bitrix для Zend OPcache при проверке настроек PHP рекомендует выставить следующие значения:
opcache.max_accelerated_files = 100000Параметр указывает, сколько хранить ключей (и, соответственно, скриптов) в хеш-таблице OPcache. Объем памяти под хеш-таблицу выделяется один раз при запуске и не изменяется в процессе работы. Если хеш-таблица заполнится, OPcache будет перезапущен.
opcache.revalidate_freq = 0Параметр указывает, как часто нужно проверять скрипты на наличие изменений. Значение "0" - проверять каждый раз при запросе скрипта. Любое другое значение указывает количество секунд.
Далее выполним некоторые настройки для OPcache, которые Bitrix не упоминает — их изменение может оптимизировать работу.
opcache.memory consumption = 128Параметр указывает значение используемой памяти для OPcache. Память выделяется сразу для всех нужд: хеш-таблиц (max_accelerated_files), кешированных строк (interned_strings_buffer) и непосредственно для кешированных данных.
opcache.max_wasted_percentage = 5Параметр устанавливает максимальный процент устаревших значений в кеше. Из-за особенностей работы OPcache, память, занятая закешированными данными, не освобождается, если данные устарели. Для предотвращения серьезного устаревания кеша, при достижении указанного в параметре значения, opcache будет перезапущен.
opcache.interned_strings_buffer = 8Параметр указывает объем буфера для кешированных строк. Чем больше статичных строк предполагается в коде, тем выше следует указывать значение. В случае переполнения буфера строк OPcache не перезапустится, а обработка строк замедлится.
opcache.save_comments = 1Параметр указывает, кешировать ли комментарии в коде. Комментарии кешируются как строки. Комментарии могут использоваться фреймворками и отключение опции может привести к их некорректной работе.
Если потребуется сбросить кеш, можно воспользоваться функциями opcache_reset или opcache_invalidate, либо перезапуском процессов PHP. Отслеживать работу OPcache и использование им памяти для корректировки настроек можно через функцию opcache_get_status.
Настройки СУБД
Перейдем к настройкам СУБД — эта задача уже поинтереснее. Некоторые настройки обычно выбираются исходя из имеющихся ресурсов на сервере. Затем их дорабатывают в зависимости от нагрузки на сервер, чтобы тот не голодал по ресурсам в моменты расчетных нагрузок и в пиковые моменты, превышающих расчетные. Также следует обратить внимание на некоторые настройки, которые ускоряют работу СУБД при работе с запросами.
Базовые настройки, которые могут быть полезны для СУБД, используемой локально для небольшого количества проектов:\
skip-names-resolveОтключаем преобразование IP-адресов в доменные имена для входящих подключений к СУБД — оно выполняется, чтобы проверить, разрешено ли подключение с указанного хоста. Отключение позволяет убрать получение доменного имени для IP-адреса, с которого пришло подключение. Однако возникает проблема: использовать доменные имена и имена хостов в качестве разрешенного узла для подключения не получится. Потребуется указывать только IP-адреса, например, 'username'@'127.0.0.1' вместо 'username'@'localhost'.
disable-log-binОтключаем бинарный лог операций. Бинарный лог обычно используется для выполнения репликации данных между серверами, либо для отката событий СУБД. В эксперименте мы будем использовать только одну СУБД и полагаться на бэкапы баз данных, сделанные системами резервного копирования, поэтому отключим бинарный лог. Это улучшит производительность за счет исключения операции записи данных в binlog.
Далее настроим параметры, которые Bitrix рекомендует выставить при проведении диагностики СУБД.
transaction-isolationTransaction isolation, или уровни изолированности транзакций — важная часть требований к транзакционной системе ACID. Буква I в сокращении как раз про это. Transaction isolation помогает решить проблемы при параллельных операциях с данными и повышает надёжность транзакций (в ущерб скорости выполнения запросов). Во многих СУБД по умолчанию используется `repeatable read`.
`read committed` — уровень изоляции, определяющий, что прочитанные данные записаны и зафиксированы другими транзакциями. Однако `read committed` не гарантирует, что при повторном чтении в пределах транзакции данные не будут изменены другими транзакциями, либо не будут добавлены новые данные.
`repeatable read` — значение параметра для многих СУБД по умолчанию. Этот уровень изоляции гарантирует, что читаемые данные в пределах транзакции не будут изменены другими транзакциями, но при этом не исключает возможности появления новых данных. Для многих СУБД проблема добавления новых данных в пределах выполняемой транзакции решается дополнительными механизмами блокировок (InnoDB).
Уровень изоляции `read committed` обеспечивает лучшую производительность, так как СУБД требуется выполнять меньшее количество блокировок. Этот режим Bitrix рекомендует выставлять в базовом варианте настроек.
В широком смысле выбор уровня изолированности транзакций — это нахождение компромисса между производительностью СУБД и необходимой согласованностью и надежностью хранения и использования данных.
innodb-strict-mode = falseВключение строгого режима работы для InnoDB. Строгий режим предполагает возврат ошибки вместо предупреждений при попытке использования недопустимых или несовместимых параметров таблиц.
innodb_buffer_pool_instances = 1Параметр регулирует, на сколько частей будет поделен буферный пул.
innodb-flush-method = O_DIRECTПараметр регулирует политику записи логов на диск. Методы отличаются системными вызовами и влиянием на пропускную способность системы ввода-вывода. В большинстве случаев рекомендуется O_DIRECT как более оптимальный для «боевых» сред с точки зрения производительности и надёжности записи.
innodb_flush_log_at_trx_commit = 2Значение по умолчанию — 1. При нем данные на диск будут записаны после совершения транзакции. При значении 0 данные записываются раз в установленное значение innodb_flush_log_at_timeout (по умолчанию 1 секунда). При значении 2 данные записываются в лог после совершения транзакции и на диск раз в установленное значение.
Значения параметра 0 и 2 дают повышенную производительность благодаря меньшему количеству операций записи. Но, в отличие от значения 1, в случае сбоя сервера возможна потеря данных, которые еще не были записаны на диск.
Параметры 0 и 2 отличаются работой с транзакциями. Параметр 2 обеспечивает запись завершенных в течение таймаута транзакций.
sync-binlog = 0Параметр регулирует политику синхронизации бинарного лога на диск. Значение по умолчанию (1) определяет синхронизацию после совершения транзакции, что требует ресурсов сервера. Значение 0 отключает синхронизацию бинарного лога средствами СУБД, полагаясь на операционную систему для записи файла бинарного лога на диск. Это может значительно повысить производительность сервера.
max_allowed_packet = 128MПараметр регулирует предельный размер одиночного пакета, который может быть передан между сервером и клиентом. Позволяет предотвращать перегрузку сервера большими пакетами данных. Если размер пакета превышен, клиент получит сообщение об ошибке.
explicit_defaults_for_timestamp = 1Параметр регулирует работу СУБД со столбцами TIMESTAMP, требуя указать значение поля по умолчанию, чтобы избежать нестандартное и неявное поведения.
Параметры, отвечающие за работу с запросами и таблицами
Настроим параметры, которые отвечают за работу с запросами и таблицами. Их значения подбирают под ресурсы сервера. Если указать максимальные значения, то СУБД может просто перестать работать, либо бороться за ресурсы с другими службами сервера.
max_connectionsПараметр устанавливает максимально разрешенное количество соединений к СУБД. Значение по умолчанию — 151. Увеличение количества соединений требует больших ресурсов сервера. При значительном увеличении значения параметра следует также увеличить ограничение на количество открытых файлов со стороны операционной системы.
table_open_cacheПараметр тесно связан с параметром max_connections, и завязан на ограничение количества открытых файлов.
MySQL в документации приводит пример: «для 200 одновременных подключений укажите размер кеша таблиц не менее 200 * n, где n — максимальное количество таблиц на объединение в любом выполняемом запросе». Помимо примерного расчётного значения, необходимо резервировать некоторое количество открытых файлов для служебных операций СУБД.
join_buffer_sizeПараметр регулирует объем буфера для операций объединения, когда требуется выполнить операцию объединения без использования индексов. Буфер выделяется для каждого соединения и, соответственно, зависит от параметра количества соединений. Значение по умолчанию 256 Кб.
sort_buffer_sizeПараметр регулирует объем буфера для соединений, в которых используются операции сортировки. Значение по умолчанию — 256 Кб. Значение возможно выставлять в пределах сессии. Согласно документации СУБД, это является предпочтительным для сессий, где sort_buffer_size может требовать большего объема буфера и связано с тем, что большие значения параметров могут замедлить выделение памяти.
innodb_buffer_pool_sizeПараметр регулирует объем буфера для данных InnoDB, один из самых важных параметров для СУБД. Больший объем буфера позволяет убрать узкое место в виде обращений к системе ввода/вывода за часто требуемыми данными. В то же время большой объем буфера требует больше времени для инициализации и запуска СУБД. Значение по умолчанию 128 Мб.
thread_cache_sizeПараметр регулирует количество закешированных потоков. Если клиент отключился, ранее созданный поток помещается в кеш для дальнейшего повторного использования. Если все закешированные ранее потоки используются, создаётся новый. Значение по умолчанию -1, что означает автоматическое вычисление значения. Параметр позволяет немного повысить производительность сервера за счёт экономии ресурсов на частое создание новых потоков при частом подключении клиентов.
tmp_table_size
Параметр регулирует размер памяти, который выделяется для создания временных таблиц. Если временная таблица превышает указанные в параметре размер, то она будет создана на диске. Значение по умолчанию 16 Мб.
max_heap_table_sizeПараметр регулирует максимальное количество памяти, которое может быть занято таблицей типа MEMORY. Связан с параметром tmp_table_size.
key_buffer_sizeПараметр регулирует размер буфера для индексов MyISAM. Так как сейчас обычно используют InnoDB, его значение устанавливают небольшим для корректной работы служебных таблиц и операций. Значение по умолчанию 8 Мб.
bulk_insert_buffer_sizeПараметр регулирует размер буфера для массовой вставки при выполнении некоторых операций. Используется для MyISAM, значение по умолчанию 8Мб.
myisam_sort_buffer_size=4Параметр регулирует объем памяти для буфера, который выделяется при создании индексов при выполнении некоторых операций. Используется для MyISAM, значение по умолчанию 8Мб.
Рассчитываем использование памяти СУБД для разных настроек
Посмотрим, какие настройки выставляет BitrixVM для конфигураций 2, 4 и 8 Гб соответственно.
Воспользуемся скриптом mysqltuner для получения информации о расчетном использовании памяти СУБД для разных настроек:
Произведем расчёт потребления ОЗУ со стороны СУБД с разными настройками, которые настраиваются в BitrixVM в зависимости от объёма ОЗУ на сервере.
| Конфигурация СУБД | По умолчанию | Для 2 Гб ОЗУ | Для 4 Гб ОЗУ | Для 8 Гб ОЗУ |
|---|---|---|---|---|
| Расчётный объем ОЗУ | 693.2M | 1.0G | 2.1G | 5.0G |
| innodb_buffer_pool_size | 134,22 MB | 402,65 MB | 1,07 GB | 3,22 GB |
| max_connections | 151 | 35 | 43 | 55 |
| bulk_insert_buffer_size | 8,39 MB | 2,10 MB | 2,10 MB | 2,10 MB |
| myisam_sort_buffer_size | 8,39 MB | 4,19 MB | 8,39 MB | 8,39 MB |
| table_open_cache | 4000 | 8096 | 8096 | 12288 |
| thread_cache_size | 9 | 96 | 96 | 128 |
| key_buffer_size | 16,78 MB | 25,17 MB | 50,33 MB | 100,66 MB |
| join_buffer_size | 262,14 KB | 4,19 MB | 8,39 MB | 14,68 MB |
| innodb_sort_buffer_size | 1,05 MB | 1,05 MB | 1,05 MB | 1,05 MB |
| myisam_sort_buffer_size | 8,39 MB | 4,19 MB | 8,39 MB | 14,68 MB |
| sort_buffer_size | 262,14 KB | 4,19 MB | 8,39 MB | 14,68 MB |
| thread_stack | 1,05 MB | 131,07 KB | 131,07 KB | 131,07 KB |
| max_heap_table_size | 16,78 MB | 100,66 MB | 134,22 MB | 134,22 MB |
| tmp_table_size | 16,78 MB | 100,66 MB | 134,22 MB | 134,22 MB |
Итоги расчетов
Как видно из таблицы, разница параметров имеет значение. Увеличение значений параметров СУБД отражается на потребляемой сервером памяти. Нехватка памяти в критические для сервера моменты может привести к возбуждению OOM Killer и нанесению визита к MySQL, как к самому объемному процессу в памяти. Если используются неоптимальные для сервера или нагрузки параметры, другие ресурсы сервера могут использоваться нерационально. Подбор параметров сразу после установки требует немалого опыта и знания используемого приложения.
И, как показывает практика, настройки СУБД не универсальные: может возникнуть момент, когда сервер больше нагружен работой скриптов, в то время как СУБД держит зарезервированными ресурсы для себя, а другие службы сервера ютятся на оставшихся. Для предотвращения подобного великие умы поделились скриптом mysqltuner. С его помощью можно получать информацию о том, сколько ресурсов СУБД нужно для его работы, исходя из сценария использования. Он собирает статистические данные о работе сервера, чтобы не собирать их вручную из разных мест, и предлагает параметры для оптимальной работы.
Если мы хотим получить больше от этого скрипта, для СУБД нужно включить performance_schema для записи событий СУБД:
performance_schema=onЗатем оставляем сервер работать некоторое время под штатной нагрузкой. Эта опция снизит общую производительность сервера. Она накладна по ресурсам, но взамен мы получаем полезную информацию о производительности сервера для дальнейшего анализа.
Даже после выполнения всех рекомендаций скрипт mysqltuner стоит периодически запускать для мониторинга производительности СУБД. Многие факты о его работе могут раскрыться со временем. Это открывает простор для дальнейшей оптимизации в зависимости от нагрузки сервера и полученной информации.
А что по попугаям? Мерим синтетическую производительность
Как известно, Битрикс процессорозависим: его синтетическая производительность, измеренная встроенным средством измерения сильно зависит от частоты процессора. Плюс, на производительность влияют настройки PHP и его режим работы. Ниже приведены замеры встроенным средством производительности. В качестве испытуемого сервера выступал ПК с Ryzen 7 9700X, 64Гб ОЗУ и SATA SSD. Процессор предварительно был переведен в производительный режим работы, чтобы его частоты не уходили в экономичный режим. Без нагрузки частота процессора была ~3.4ГГц, под нагрузкой ~5.4ГГц. Сайт был создан с версией PHP 8.3.24.
В таблице ниже за номерами скрываются следующие замеры:
- №1 — чистый сайт, PHP в режиме Модуль Apache (Nginx+Apache)
- №2 — то же,что №1, но отключен open_basedir
- №3 — то же,что №2, но изменен opcache.max_accelerated_files
- №4 — то же, что №3 но добавлены настройки PHP
- №5 — PHP в режиме PHP-FPM (Nginx)
- №6 — то же, что №5, но добавлены настройки PHP
| Замер | №1 | №2 | №3 | №4 | №5 | №6 |
|---|---|---|---|---|---|---|
| Конфигурация | 106.76 | 201.34 | 200.00 | 200.45 | 238.10 | 226.70 |
| Среднее время отклика | 0.0094 | 0.0050 | 0.0050 | 0.0050 | 0.0042 | 0.0044 |
| Процессор (CPU) | 986.3 | 958.2 | 962.1 | 978.4 | 800.3 | 801.3 |
| Файловая система | 27 858.5 | 70 002.9 | 69 357.9 | 69 987.2 | 69 485.6 | 69 331.8 |
| Почтовая система | 0.0064 | 0.0067 | 0.0069 | 0.0066 | 0.0068 | 0.0072 |
| Время старта сессии | 0.0000 | 0.0000 | 0.0000 | 0.0000 | 0.0000 | 0.0000 |
| Конфигурация PHP | N | Y | Y | Y | Y | Y |
| База данных MySQL (запись) | 971 | 993 | 977 | 1 013 | 938 | 962 |
| База данных MySQL (чтение) | 89 068 | 87 533 | 92 451 | 92 309 | 94 686 | 85 053 |
| База данных MySQL (изменение) | 64 301 | 65 775 | 66 313 | 65 639 | 60 276 | 62 832 |
Как видим, отключение open_basedir приводит к существенному повышению производительности. Причина в том, что при заданном параметре open_basedir интерпретатор PHP выполняет проверку расположения файла: если файл лежит вне указанных директорий, будет выброшено соответствующее исключение. Отключение параметра позволяет исключить подобные проверки, что положительно скажется на производительности, но в ущерб безопасности.
Также при приведении параметров PHP к рекомендуемому виду для Bitrix производительность сайта в «попугаях» начинает падать. Это связано с тем, что большая часть параметров направлена на увеличение потребляемой и выделяемой памяти для PHP, и ее резервирование также требует определенных мощностей.
С версии 6.123 в ispmanager появилась возможность использовать веб-сервер LiteSpeed, проведем замеры и с ним.
| Замеры производительности с LiteSpeed | Чистый сайт | Добавлены настройки PHP |
|---|---|---|
| Конфигурация | 257.88 | 238.10 |
| Среднее время отклика | 0.0039 | 0.0042 |
| Процессор (CPU) | 804.4 | 916.0 |
| Файловая система | 70 686.2 | 70 102.7 |
| Почтовая система | 0.0069 | 0.0063 |
| Время старта сессии | 0.0000 | 0.0000 |
| Конфигурация PHP | Y | Y |
| База данных MySQL (запись) | 30 997 | 35 219 |
| База данных MySQL (чтение) | 89 381 | 79 601 |
| База данных MySQL (изменение) | 70 396 | 75 043 |
Показатели в сравнении с другими веб-серверами хорошие при том, что с LiteSpeed можно работать как с Apache2 (он использует конфигурационные файлы Apache2, поддерживает .htaccess).
И напоследок сделаем замер производительности сайта в режиме Модуль Apache с настройками для СУБД.
| Конфигурация | 200.45 |
| Среднее время отклика | 0.0050 |
| Процессор (CPU) | 947.4 |
| Файловая система | 69 916.3 |
| Почтовая система | 0.0088 |
| Время старта сессии | 0.0000 |
| Конфигурация PHP | Y |
| База данных MySQL (запись) | 36 445 |
| База данных MySQL (чтение) | 80 959 |
| База данных MySQL (изменение) | 69 908 |
Как видим, цифры выросли, но не так впечатляюще, как хотелось бы. Всему виной не самое быстрое постоянное хранилище (NVMe помог бы получить дополнительные баллы).
Настройки, отличающиеся от настроек по умолчанию, которые были установлены для измерений:
| Настройки PHP: | Настройки СУБД: |
|---|---|
| short_open_tag = On | innodb-strict-mode = false |
| max_input_vars=10000 | collation-server = utf8mb4_0900_ai_ci |
| mbstring.func_overload=0 | character-set-server = utf8mb4 |
| mbstring.internal_encoding=utf-8 | skip-names-resolve |
| upload_max_filesize=64M | innodb_flush_log_at_trx_commit = 2 |
| post_max_size=64M | sync-binlog = 0 |
| opcache.max_accelerated_files=100000 | innodb-flush-method = O_DIRECT |
| realpath_cache_size=4096k | transaction-isolation = READ-COMMITTED |
| memory_limit = 512M | |
| pcre.jit = 0 | |
| opcache.revalidate_freq = 0 | |
| max_execution_time=120 |
Другие настройки выставлялись в зависимости от объема ОЗУ для замера.
И для общего сравнения ниже приведена таблица замеров производительности Bitrix (1С-Битрикс: Веб-окружение, bitrix-env-9) для разных сред, отличающихся между собой. Собственно, среды:
- Старый, но не бесполезный, Intel NUC, 2 ядра CPU (i5-6260U, отключена многопоточность), 8Gb RAM.
- Виртуальный сервер с тарифом, заточенным для Bitrix, — с высокой производительностью процессора. 2 ядра CPU (по информации системы - Ryzen 9 9950X), 2Gb RAM.
- Сборка «мама, это для учёбы»: Ryzen 7 9700X 8(16) CPU, 64Gb RAM.
| Среда №1 | Среда №2 | Среда №3 | |
| Конфигурация | 99.56 | 165.14 | 290.32 |
| Среднее время отклика | 0.0100 | 0.0061 | 0.0034 |
| Процессор (CPU) | 336.0 | 1 004.8 | 1 023.1 |
| Дисковая система | 11 035.5 | 14 083.2 | 62 257.0 |
| Почтовая система | 0.0092 | 0.0073 | 0.0032 |
| Время старта сессии | 0.0001 | 0.0000 | 0.0000 |
| Конфигурация PHP | Y | Y | Y |
| База данных MySQL (запись) | 8 506 | 7 289 | 47 693 |
| База данных MySQL (чтение) | 11 836 | 50 660 | 104 848 |
| База данных MySQL (изменение) | 7 192 | 21 301 | 64 979 |
Эксперимент подтвердил бытующее мнение, что Bitrix процессорозависим, и если хочется большого количества попугаев, то быстрое и дорогое железо — ваш выбор. Для комфортной работы можно обойтись средним железом или VPS, проведя оптимизацию среды под планируемую нагрузку.
На синтетических тестах и попугаях производительности сложно сделать объективные выводы о влиянии настроек в долгосрочной перспективе — и мы будем рады, если вы поделитесь в Telegram, каким образом вы сами настраиваете ПО сервера — для Bitrix и других CMS, или же для других задач.