Управління продуктивністю
Передчасна оптимізація — корінь усього зла.
Можливо ви вже читали цю цитату раніше. Але я хотів би навести її повністю:
Нам слід забути про невелику ефективність, скажімо, у 97% випадків: передчасна оптимізація — корінь усього зла. Однак ми не маємо упускати наші можливості в цих критичних 3%.
-- Donald Knuth
Навіть невеликі поліпшення продуктивності можуть щось змінити, особливо для веб-сайтів електронної комерції. Тепер, коли застосунок гостьової книги готовий до прайм-тайму, подивімося, як ми можемо перевірити його продуктивність.
Найкращим способом пошуку потенційно слабких місць для оптимізації продуктивності є використання профілювальника. Найпопулярнішим варіантом сьогодні є Blackfire (повна відмова від відповідальності: я також є засновником проекту Blackfire).
Знайомство з Blackfire
Blackfire складається з кількох частин:
- Клієнт, який запускає профілювання (інструмент Blackfire CLI чи розширення браузера Google Chrome або Firefox);
- Агент, який готує й агрегує дані перед їх відправкою в blackfire.io для відображення;
- Розширення PHP (зонд), яке аналізує код PHP.
Щоб працювати з Blackfire, вам спочатку потрібно зареєструватися.
Встановіть Blackfire на ваш локальний комп'ютер, запустивши наступний сценарій швидкого встановлення:
1
$ curl https://installer.blackfire.io/installer.sh | bash
Цей інсталятор завантажує і встановлює інструмент Blackfire CLI.
Після завершення встановлює зонд PHP на всі доступні версії PHP:
1
$ sudo blackfire php:install
І увімкніть зонд PHP для нашого проекту:
1 2 3 4 5 6 7 8 9 10
--- a/php.ini
+++ b/php.ini
@@ -7,3 +7,7 @@ session.use_strict_mode=On
realpath_cache_ttl=3600
zend.detect_unicode=Off
xdebug.file_link_format=vscode://file/%f:%l
+
+[blackfire]
+# use php_blackfire.dll on Windows
+extension=blackfire.so
Перезавантажте веб-сервер, щоб PHP міг завантажити Blackfire:
1 2
$ symfony server:stop
$ symfony server:start -d
Інструмент Blackfire CLI потрібно налаштувати за допомогою ваших клієнтських облікових даних (щоб зберігати профілі проектів у вашому особистому кабінеті). Знайдіть їх у верхній частині сторінки Settings/Credentials
і виконайте наступну команду, замінивши заповнювачі:
1
$ blackfire client:config --client-id=xxx --client-token=xxx
Налаштування агента Blackfire у Docker
Сервіс агента Blackfire вже налаштований у стеку Docker Compose:
Щоб організувати обмін інформацією з сервером вам потрібно отримати ваші особисті серверні облікові дані (ці облікові дані визначають, де ви хочете зберігати профілі — ви можете створити один для кожного проекту); їх можна знайти в нижній частині сторінки Settings/Credentials`. Збережіть їх у локальному файлі
.env.local``:
1 2 3 4
$ symfony console secrets:set BLACKFIRE_SERVER_ID
# xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
$ symfony console secrets:set BLACKFIRE_SERVER_TOKEN
# xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Тепер ви можете запустити новий контейнер:
1 2
$ docker-compose stop
$ docker-compose up -d
Виправлення помилок Blackfire
Якщо ви отримуєте помилку під час профілювання, збільште рівень журналювання Blackfire, щоб отримувати більше інформації в журналах:
1 2 3 4 5 6 7
--- a/php.ini
+++ b/php.ini
@@ -10,3 +10,4 @@ zend.detect_unicode=Off
[blackfire]
# use php_blackfire.dll on Windows
extension=blackfire.so
+blackfire.log_level=4
Перезавантажте веб-сервер:
1 2
$ symfony server:stop
$ symfony server:start -d
І стежте за журналом:
1
$ symfony server:log
Відпрофілюйте ще раз і перевірте вивід журналу.
Налаштування Blackfire в продакшн
Blackfire включено у всі проекти Platform.sh за замовчуванням.
Налаштуйте серверні облікові дані як конфіденційні дані продакшн:
1 2 3 4
$ symfony console secrets:set BLACKFIRE_SERVER_ID --env=prod
# xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
$ symfony console secrets:set BLACKFIRE_SERVER_TOKEN --env=prod
# xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Зонд PHP уже ввімкнено, як і будь-яке інше необхідне розширення PHP:
Налаштування Varnish для Blackfire
Перш ніж ви зможете розгорнути, щоб почати профілювання, вам потрібен спосіб, щоб обійти HTTP-кеш Varnish. Якщо ні, то Blackfire ніколи не потрапить у застосунок PHP. Ви збираєтеся дозволити обхід Varnish тільки для запитів профілювання, що надходять з вашого локального комп'ютера.
Знайдіть свою поточну IP-адресу:
1
$ curl https://ifconfig.me/
І використовуйте її для налаштування Varnish:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
--- a/.platform/config.vcl
+++ b/.platform/config.vcl
@@ -1,3 +1,11 @@
+acl profile {
+ # Authorize the local IP address (replace with the IP found above)
+ "192.168.0.1";
+ # Authorize Blackfire servers
+ "46.51.168.2";
+ "54.75.240.245";
+}
+
sub vcl_recv {
set req.backend_hint = application.backend();
set req.http.Surrogate-Capability = "abc=ESI/1.0";
@@ -8,6 +16,16 @@ sub vcl_recv {
}
return (purge);
}
+
+ # Don't profile ESI requests
+ if (req.esi_level > 0) {
+ unset req.http.X-Blackfire-Query;
+ }
+
+ # Bypass Varnish when the profile request comes from a known IP
+ if (req.http.X-Blackfire-Query && client.ip ~ profile) {
+ return (pass);
+ }
}
sub vcl_backend_response {
Тепер ви можете розгорнути.
Профілювання веб-сторінок
Ви можете профілювати традиційні веб-сторінки з Firefox чи Google Chrome за допомогою їх спеціальних розширень.
Під час профілювання не забудьте вимкнути HTTP-кеш на вашому локальному комп'ютері, у файлі config/packages/framework.yaml
: якщо ні, ви профілюватимите шар HTTP-кешу Symfony, замість власного коду.
Щоб отримати краще уявлення про продуктивність вашого застосунку в продакшн, вам також слід профілювати "production" середовище. За замовчуванням ваше локальне середовище використовує середовище "development", яке додає значні накладні витрати (в основному для збору даних для панелі інструментів веб-наладження і профілювальника Symfony).
Note
Оскільки ми будемо профільувати «продакшн» середовище, у конфігурації нічого змінювати не потрібно, оскільки ми ввімкнули рівень HTTP-кешу Symfony лише для середовища «розробки» в попередньому розділі.
Перемкнути ваш локальний комп'ютер у продакшн середовище можна змінивши змінну середовища APP_ENV
у файлі .env.local
:
1
APP_ENV=prod
Або ви можете використовувати команду server:prod
:
1
$ symfony server:prod
Не забудьте перемкнути її назад у середовище розробки, коли ваш сеанс профілювання завершиться:
1
$ symfony server:prod --off
Профілювання ресурсів API
Профілювання API чи ОЗ краще виконувати за допомогою Blackfire CLI, інструменту, який ви встановили раніше:
1
$ blackfire curl `symfony var:export SYMFONY_PROJECT_DEFAULT_ROUTE_URL`api
Команда blackfire curl
приймає точно ті самі аргументи й параметри, що й cURL.
Порівняння продуктивності
На кроці про "Кеш" ми додали шар кешу, щоб поліпшити продуктивність нашого коду, але ми не перевіряли й не вимірювали вплив цієї зміни на продуктивність. Оскільки нам важко здогадатися, що буде швидким, а що повільним — ви можете опинитися в ситуації, коли деяка оптимізація насправді уповільнює ваш застосунок.
Ви завжди маєте вимірювати вплив будь-якої оптимізації, яку ви робите, за допомогою профілювальника. Blackfire робить це візуально простішим, завдяки своїй функції порівняння.
Написання функціональних тестів "чорної скриньки"
Ми вже бачили, як писати функціональні тести за допомогою Symfony. Blackfire можна використовувати для написання сценаріїв перегляду, які можуть бути виконані за запитом, за допомогою Blackfire player. Напишімо сценарій, який відправляє новий коментар і перевіряє його за посиланням електронної пошти у середовищі розробки й за допомогою адміністратора у продакшн.
Створіть файл .blackfire.yaml
із наступним вмістом:
Завантажте Blackfire Player, щоб мати можливість виконувати сценарій локально:
1 2
$ curl -OLsS https://get.blackfire.io/blackfire-player.phar
$ chmod +x blackfire-player.phar
Виконайте цей сценарій у режимі розробки:
1
$ ./blackfire-player.phar run --endpoint=`symfony var:export SYMFONY_PROJECT_DEFAULT_ROUTE_URL` .blackfire.yaml --variable "webmail_url=`symfony var:export MAILER_WEB_URL 2>/dev/null`" --variable="env=dev" -vv
1
$ rm blackfire-player.phar
Або в продакшн:
1
$ ./blackfire-player.phar run --endpoint=`symfony cloud:env:url --pipe --primary` .blackfire.yaml --variable "webmail_url=NONE" --variable="env=prod" -vv
Сценарії Blackfire також можуть профілювати кожен запит і виконувати тести продуктивності, додавши прапорець --blackfire
.
Автоматизація перевірок продуктивності
Управління продуктивністю полягає не тільки в поліпшенні продуктивності наявного коду, але і в перевірці того, що внесені зміни не призводять до її регресії.
Сценарій, що написаний у попередньому розділі, може виконуватися автоматично в робочому процесі безперервної інтеграції або у продакшн, на регулярній основі.
Platform.sh також дозволяє виконувати сценарії щоразу, коли ви створюєте нову гілку чи розгортаєте у продакшн, щоб автоматично перевірити продуктивність нового коду.