Upgrade to Pro — share decks privately, control downloads, hide ads and more …

«Боремся с shared-nothing моделью: PHP 7.4 prel...

Avatar for Badoo Tech Badoo Tech
September 21, 2019

«Боремся с shared-nothing моделью: PHP 7.4 preload, RoadRunner и другие» — Павел Мурзаков (Badoo)

Badoo PHP Meetup #3

Традиционное PHP-приложение (т.е. mod_php, php-fpm и т. п.) каждый раз исполняет весь код с нуля. Это значит, что весь bootstrap приложения происходит заново на каждый запрос: инициализация окружения, подключение необходимых файлов, сборка DI-контейнеров, загрузка конфигов и прочее. Всё это одинаково для каждого запроса, и могло быть сделано один раз, но PHP приходится постоянно повторять эти действия. Поэтому, даже если бизнес-логика достаточно оптимизирована, мы всё равно будем тратить ресурсы впустую на инициализацию.

В докладе поговорим, как можно решить или минимизировать эту проблему:

Разберёмся, на что именно тратятся ресурсы, посмотрим в perf и исходники PHP.
Поищем какие-то простые решения проблемы: как мы можем делать меньше инициализаций или сохранить данные между запросами.
Опробуем новые достижения PHP-сообщества — PHP 7.4 preload и RoadRunner — и сравним их.
Разберёмся, зачем нужен PHP 7.4 preload, если уже есть opcache, и как выжать из RoadRunner ещё больше.

Avatar for Badoo Tech

Badoo Tech

September 21, 2019
Tweet

More Decks by Badoo Tech

Other Decks in Technology

Transcript

  1. 7M строк кода на PHP 600 cерверов с PHP-FPM 120K

    запросов в секунду в пиках 2
  2. • Не шарит состояние между PHP worker’ами • Не сохраняет

    состояние между запросами Классический PHP 9 Shared Nothing architecture PHP
  3. • Подключить файлы • Инициализировать фреймворк, библиотеки, etc • Запросить

    данные из внешних хранилищ Повторяющиеся действия 20 Shared Nothing architecture PHP
  4. Что делать? 21 • Shared memory, apcu, … • Хранение

    данных в IS_ARRAY_IMMUTABLE массивах • Батчинг/объединение запросов • Тюнить opcache • … Производительность PHP: планируем, профилируем, оптимизируем https://habr.com/ru/company/badoo/blog/430722/ Shared Nothing architecture PHP
  5. • Подключить файлы (opcache?) • Инициализировать фреймворк, библиотеки, etc •

    Запросить данные из внешних хранилищ Повторяющиеся действия 23 Preload (PHP 7.4) Проблема
  6. # perf record --call-graph dwarf,65528 -F 99 -p \ $(pgrep

    php-cgi | paste -sd "," -) -- sleep 20 # perf report 24
  7. 25

  8. “opcode caches … achieve significant performance boost by ALMOST completely

    eliminating the overhead of PHP code recompilation” https://wiki.php.net/rfc/preload
  9. • Symfony 4 подключает ~310 файлов • Зависимости Composer’а (особенно

    объявляющие функции) Производительность include 32 Preload (PHP 7.4) Проблема
  10. Бенчмарки 37 • Что: один endpoint продакшена Badoo (CPU-bound) •

    Как: preload’им все нужные файлы Preload (PHP 7.4) Решение
  11. Бенчмарки 38 • Что: один endpoint продакшена Badoo (CPU-bound) •

    Как: preload’им все нужные файлы • Чем: wrk2 Preload (PHP 7.4) Решение
  12. • PHP 7.2: 845 rps • PHP 7.4: 931 rps

    (+10%) 40 Бенчмарки — результаты Preload (PHP 7.4) Решение
  13. • PHP 7.2: 845 rps • PHP 7.4: 931 rps

    (+10%) • PHP 7.4 + preload: ??? rps 41 Бенчмарки — результаты Preload (PHP 7.4) Решение
  14. • PHP 7.2: 845 rps • PHP 7.4: 931 rps

    (+10%) • PHP 7.4 + preload: 1030 rps (+10% more) 42 Бенчмарки — результаты Preload (PHP 7.4) Решение
  15. 47 Резолв зависимостей Preload (PHP 7.4) Нюансы PHP Warning: Can't

    preload class MyTestClass with unresolved initializer for constant RAND in /local/mdk/code/preload- internal.php on line 5 PHP Warning: Can't preload unlinked class MyTestClass: Unknown parent AnotherClass in /local/mdk/code/preload-internal.php on line 5
  16. 50 opcache_compile_file VS include Preload (PHP 7.4) Нюансы • include/require

    • фактически исполняет код (в т.ч. вызывает автолоадер)
  17. 51 opcache_compile_file VS include Preload (PHP 7.4) Нюансы • include/require

    • фактически исполняет код (в т.ч. вызывает автолоадер) • удаляет константы/переменные по окончанию фазы preload Preload (PHP 7.4) Нюансы
  18. 52 opcache_compile_file VS include Preload (PHP 7.4) Нюансы • include/require

    • фактически исполняет код (в т.ч. вызывает автолоадер) • удаляет константы/переменные по окончанию фазы preload • в памяти остаются только функции/классы
  19. 53 opcache_compile_file VS include Preload (PHP 7.4) Нюансы • include/require

    • фактически исполняет код (в т.ч. вызывает автолоадер) • удаляет константы/переменные по окончанию фазы preload • в памяти остаются только функции/классы • opcache_compile_file() — просто компилирует
  20. 54 opcache_compile_file VS include Preload (PHP 7.4) Нюансы include: OK

    opcache_compile_file: PHP Warning: Can't preload class MyTestClass with unresolved initializer for constant RAND in /local/mdk/code/preload- internal.php on line 5
  21. 55 opcache_compile_file VS include Preload (PHP 7.4) Нюансы include: PHP

    Fatal error: Class 'NotPreloadedClass' not found in /local/ mdk/code/preload-internal.php on line 5 opcache_compile_file: PHP Warning: Can't preload unlinked class MyTestClass: Unknown parent AnotherClass in /local/mdk/code/preload- internal.php on line 5
  22. • Изменение кода = перезапуск(reload) php-fpm/apache • Зависимости обязательно разрезолвлены

    • opcache_compile_file() VS include/require • Поля/константы класса: preload VS runtime 56 Preload (PHP 7.4) Нюансы
  23. • Изменение кода = перезапуск(reload) php-fpm/apache • Зависимости обязательно разрезолвлены

    • opcache_compile_file() VS include/require • Константы класса preload VS runtime • Cannot redeclare … function 58 Preload (PHP 7.4) Нюансы
  24. • Изменение кода = перезапуск(reload) php-fpm/apache • Зависимости обязательно разрезолвлены

    • opcache_compile_file() VS include/require • Константы класса preload VS runtime • Cannot redeclare … function • PHP 7.4 не production-ready (пока) 60 Preload (PHP 7.4) Нюансы
  25. • Подключить файлы • Инициализировать фреймворк, библиотеки, etc • Запросить

    данные из внешних хранилищ Повторяющиеся действия 65 RoadRunner
  26. Повторяющиеся действия 66 RoadRunner • Подключить файлы • Инициализировать фреймворк,

    библиотеки, etc • Запросить данные из внешних хранилищ
  27. • PHP 7.4 (FPM): 931 rps • PHP 7.4 (FPM)

    + preload: 1030 rps (+10%) 73 Бенчмарки — результаты RoadRunner
  28. • PHP 7.4 (FPM): 931 rps • PHP 7.4 (FPM)

    + preload: 1030 rps (+10%) • PHP 7.4 RoadRunner: ??? rps 74 Бенчмарки — результаты RoadRunner
  29. • PHP 7.4 (FPM): 931 rps • PHP 7.4 (FPM)

    + preload: 1030 rps (+10%) • PHP 7.4 RoadRunner: 987 rps (+6%) 75 Бенчмарки — результаты RoadRunner
  30. 76 Бенчмарки — результаты RoadRunner WAT ?! • PHP 7.4

    (FPM): 931 rps • PHP 7.4 (FPM) + preload: 1030 rps (+10%) • PHP 7.4 RoadRunner: 987 rps (+6%)
  31. 79 Бенчмарки — результаты RoadRunner • PHP 7.4 (FPM): 931

    rps • PHP 7.4 (FPM) + preload: 1030 rps (+10%) • PHP 7.4 RoadRunner: 987 rps (+6%) • PHP 7.4 RoadRunner + Opcache: 1049 rps (+12%)
  32. 88 Бенчмарки — результаты RoadRunner • PHP 7.4 (FPM): 931

    rps • PHP 7.4 (FPM) + preload: 1030 rps (+10%) • PHP 7.4 RoadRunner: 987 rps (+6%) • PHP 7.4 RoadRunner + Opcache: 1049 rps (+12%) • PHP 7.4 RoadRunner + Opcache + no PSR 7: 1089 rps (+17%)
  33. • Код становится сложнее, сложнее поддерживать, проще допускать ошибки •

    Чтобы выжать максимум, нужно писать код “под демон” изначально 91 RoadRunner Нюансы
  34. • Код становится сложнее, сложнее поддерживать, проще допускать ошибки •

    Чтобы выжать максимум нужно писать код “под демон” изначально • Тестировалось на наших кейсах, на одном запросе 92 RoadRunner Нюансы
  35. А почему не Swoole? А почему не amPHP? А почему

    не ReactPHP? А почему не $OtherAsyncPHP$?
  36. 1. Shared Nothing — благо 2. Shared Nothing можно оптимизировать

    3. PHP 7.4 с preload добавят производительность (с минимумом сложностей) 100
  37. 1. Shared Nothing — благо 2. Shared Nothing можно оптимизировать

    3. PHP 7.4 с preload добавят производительность (с минимумом сложностей) 4. RoadRunner сложнее, но ещё производительнее 101