# Производительность

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

## Количество потоков и worker-скриптов

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

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

Чтобы найти подходящие параметры, лучше всего провести нагрузочные тесты, имитирующие реальный трафик.  
Хорошими инструментами для этого являются [k6](https://k6.io) и [Gatling](https://gatling.io).

Чтобы настроить количество потоков, используйте опцию `num_threads` в директивах `php_server` и `php`.  
Для изменения количества worker-скриптов используйте опцию `num` в секции `worker` директивы `frankenphp`.

## Worker режим

Включение [Worker режима](worker.md) значительно улучшает производительность,  
но ваше приложение должно быть адаптировано для совместимости с этим режимом:  
необходимо создать worker-скрипт и убедиться, что приложение не имеет утечек памяти.

## Избегайте использования musl

Статические бинарники, которые мы предоставляем, а также Alpine Linux-вариант официальных Docker-образов используют [библиотеку musl libc](https://musl.libc.org).

Известно, что PHP [значительно медленнее работает](https://gitlab.alpinelinux.org/alpine/aports/-/issues/14381) с этой библиотекой по сравнению с традиционной GNU libc, особенно при компиляции в ZTS режиме (потокобезопасный режим), который требуется для FrankenPHP.

Кроме того, [некоторые ошибки проявляются исключительно при использовании musl](https://github.com/php/php-src/issues?q=sort%3Aupdated-desc+is%3Aissue+is%3Aopen+label%3ABug+musl).

В производственной среде настоятельно рекомендуется использовать glibc.

Это можно сделать, используя Debian Docker-образы (по умолчанию) и [компилируя FrankenPHP из исходников](compile.md).

В качестве альтернативы мы предоставляем статические бинарники, скомпилированные с [аллокатором mimalloc](https://github.com/microsoft/mimalloc), что делает FrankenPHP+musl быстрее (но всё же медленнее, чем FrankenPHP+glibc).

## Настройка среды выполнения Go

FrankenPHP написан на языке Go.

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

Рекомендуется установить переменную окружения `GODEBUG` в значение `cgocheck=0` (по умолчанию в Docker-образах FrankenPHP).

Если вы запускаете FrankenPHP в контейнерах (Docker, Kubernetes, LXC и т.д.) и ограничиваете доступную память, установите переменную окружения `GOMEMLIMIT` в значение доступного объёма памяти.

Для более детальной информации ознакомьтесь с [документацией Go по этой теме](https://pkg.go.dev/runtime#hdr-Environment_Variables).

## `file_server`

По умолчанию директива `php_server` автоматически настраивает файловый сервер для обслуживания статических файлов (ресурсов), хранящихся в корневой директории.

Эта функция удобна, но имеет издержки. Чтобы отключить её, используйте следующую конфигурацию:

```caddyfile
php_server {
    file_server off
}
```

## Плейсхолдеры

Вы можете использовать [плейсхолдеры](https://caddyserver.com/docs/conventions#placeholders) в директивах `root` и `env`.  
Однако это предотвращает кеширование значений и существенно снижает производительность.

По возможности избегайте использования плейсхолдеров в этих директивах.

## `resolve_root_symlink`

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

```caddyfile
php_server {
    resolve_root_symlink false
}
```

Это улучшит производительность, если директива `root` содержит [плейсхолдеры](https://caddyserver.com/docs/conventions#placeholders).  
В остальных случаях прирост производительности будет минимальным.

## Логи

Логирование, безусловно, полезно, но требует операций ввода-вывода и выделения памяти, что значительно снижает производительность.  
Убедитесь, что вы [правильно настроили уровень логирования](https://caddyserver.com/docs/caddyfile/options#log) и логируете только необходимое.

## Производительность PHP

FrankenPHP использует официальный интерпретатор PHP.  
Все стандартные оптимизации производительности PHP применимы к FrankenPHP.

В частности:

- убедитесь, что [OPcache](https://www.php.net/manual/en/book.opcache.php) установлен, включён и настроен должным образом;
- включите [оптимизацию автозагрузки Composer](https://getcomposer.org/doc/articles/autoloader-optimization.md);
- убедитесь, что кеш `realpath` достаточно велик для нужд вашего приложения;
- используйте [предварительную загрузку](https://www.php.net/manual/en/opcache.preloading.php).

Для более детальной информации ознакомьтесь с [документацией Symfony о производительности](https://symfony.com/doc/current/performance.html) (большинство советов полезны даже если вы не используете Symfony).
