Питання на співбесіді: Performance
Найпопулярніші питання з реальних Laravel/PHP співбесід для всіх рівнів
7 питань
php artisan route:cache компілює всі маршрути в один файл, тож фреймворк не реєструє їх заново на кожному запиті - це помітно пришвидшує бутстрап на застосунках із сотнями маршрутів.
php artisan route:cache # на деплої
php artisan route:clear # скинути
Лише для продакшену. Обмеження: маршрути на основі замикань кешувати не можна - потрібні контролери. Команда php artisan optimize кешує маршрути, конфіг та події разом.
Оптимізація йде кількома шарами:
База даних
- Усунення 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 і перезапускає воркери для безпеки.
Ключове правило - не тримати весь файл у пам'яті.
- Стрімінг замість читання цілком:
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 мають змінюватися атомарно, інакше за конкурентного доступу ліміт «протікає».
Одна команда робить більшість:
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 лишається розумним дефолтом, доки немає потреби в екстремальній продуктивності.