Блог
Кар'єра
Вакансії Компанії
Навчання
Співбесіди Тестування Відео
Екосистема
Пакети Ресурси
Інше
Події Про нас

Питання на співбесіді: Performance

Найпопулярніші питання з реальних Laravel/PHP співбесід для всіх рівнів

7 питань

php artisan route:cache компілює всі маршрути в один файл, тож фреймворк не реєструє їх заново на кожному запиті - це помітно пришвидшує бутстрап на застосунках із сотнями маршрутів.

php artisan route:cache    # на деплої
php artisan route:clear    # скинути

Лише для продакшену. Обмеження: маршрути на основі замикань кешувати не можна - потрібні контролери. Команда php artisan optimize кешує маршрути, конфіг та події разом.

Докладніше в документації: Оптимізація: Route Caching

Оптимізація йде кількома шарами:

База даних

  • Усунення N+1 (eager loading with()), правильні індекси, аналіз через EXPLAIN.
  • Read/write репліки, кешування важких запитів.

Кешування

  • Cache::remember() для дорогих обчислень; повне кешування сторінок/фрагментів.
  • php artisan optimize (config/route/view/event cache), OPcache.

Фонова робота

  • Винесення повільних задач (email, обробка медіа, виклики API) у черги.

Інфраструктура

  • Laravel Octane (Swoole/FrankenPHP) тримає застосунок у пам'яті.
  • CDN для статики, горизонтальне масштабування за load balancer, спільні сесії/кеш у Redis.

Перед оптимізацією - профілювання (Telescope, Clockwork, Debugbar), щоб бити по реальних вузьких місцях.

Докладніше в документації: Оптимізація для деплою

Octane запускає застосунок через high-performance сервери (Swoole, FrankenPHP, RoadRunner): фреймворк бутстрапиться один раз і тримається в пам'яті, обслуговуючи наступні запити без повторної ініціалізації.

php artisan octane:start --server=frankenphp

Це усуває оверхед завантаження на кожному запиті й дає кратний приріст RPS.

Підводні камені: оскільки процес довготривалий, треба уникати витоків стану між запитами - статичні властивості, синглтони з накопиченим станом, глобальні змінні можуть «протікати» від запиту до запиту. Octane надає хуки flush і перезапускає воркери для безпеки.

Докладніше в документації: Laravel Octane

Ключове правило - не тримати весь файл у пам'яті.

  • Стрімінг замість читання цілком:
    return Storage::disk('s3')->response($path); // стрім на скачування
    Storage::writeStream($path, fopen($source, 'r')); // стрім на запис
    
  • Direct uploads на S3 - клієнт вантажить напряму в сховище за pre-signed URL, минаючи PHP-процес (не блокує воркер, обходить ліміти upload_max_filesize).
  • Chunked upload - великі файли частинами (resumable).
  • Фонова обробка - конвертацію відео/зображень виносити в черги.
  • Враховувати max_execution_time, таймаути nginx і ліміти пам'яті воркера.

Докладніше в документації: Зберігання файлів (стрімінг)

У кластері з кількох інстансів локальний лічильник не годиться - потрібен спільний стан у Redis. Фасад RateLimiter під капотом використовує атомарні операції Redis (INCR + EXPIRE), тож підрахунок точний між усіма серверами.

RateLimiter::attempt(
    key: 'send-sms:'.$user->id,
    maxAttempts: 5,
    callback: fn () => $this->sendSms(),
    decaySeconds: 60,
);

Для складніших схем - алгоритми sliding window чи token bucket на Lua-скриптах (атомарність на стороні Redis, без гонок). Ключове: лічильник і його TTL мають змінюватися атомарно, інакше за конкурентного доступу ліміт «протікає».

Докладніше в документації: Rate Limiting

Одна команда робить більшість:

php artisan optimize        # config + route + view + event cache

Окремо:

php artisan config:cache # об'єднує конфіг у один файл
php artisan route:cache # компілює маршрути
php artisan view:cache # прекомпілює Blade
php artisan event:cache # кеш мапінгу подій/слухачів
composer install --no-dev --optimize-autoloader

Додатково: увімкнений OPcache (а краще з JIT), prebuilt ассети (npm run build).

Підводний камінь: після config:cache виклики env() поза config/ повертають null - усі env-значення мають читатися лише у конфіг-файлах. На деплої не забути php artisan optimize:clear перед повторним кешуванням.

Докладніше в документації: Оптимізація для деплою

PHP-FPM - «shared nothing»: кожен запит стартує з чистого стану, наприкінці все звільняється. Просто, безпечно, але є оверхед бутстрапу фреймворку на кожному запиті.

Octane тримає застосунок у пам'яті між запитами → кратно вищий throughput і нижча латентність.

PHP-FPM Octane
Стан між запитами чистий зберігається
Throughput нижчий значно вищий
Ризик витоків стану немає є
Складність деплою проста вища (воркери, рестарти)

Ціна Octane: треба остерігатися «протікання» стану (статика, синглтони, глобальні змінні), правильно скидати/перезапускати воркери, уважно з пам'яттю. FPM лишається розумним дефолтом, доки немає потреби в екстремальній продуктивності.

Докладніше в документації: Laravel Octane