PHP's built-in performance superpowers.
Many production Laravel servers run with OpCache disabled. This means every single request recompiles every PHP file. Without OpCache, your Laravel app is 2-3x slower than it should be. It's the most common and easiest performance fix.
| Scenario | Without OpCache | With OpCache | Improvement |
|---|---|---|---|
| First request (after clear) | 50ms | 50ms | Same (must compile once) |
| Subsequent requests (cold cache) | 45ms | 10ms | 4.5x faster |
| Subsequent requests (warm cache) | 45ms | 3ms | 15x faster |
| 100,000 requests/day | ~4,500 seconds CPU | ~300 seconds CPU | 93% reduction |
OpCache is not optional for production. Without it, you're wasting 30-50ms per request on compilation. With it, your server can handle 3-4x more traffic with the same hardware.
; /etc/php/8.2/cli/conf.d/10-opcache.ini
; OR /etc/php/8.2/fpm/conf.d/10-opcache.ini
[opcache]
; Enable OpCache (MANDATORY)
opcache.enable=1
opcache.enable_cli=0 ; Not needed for CLI (artisan commands)
; Memory settings (adjust based on your app size)
opcache.memory_consumption=128 ; MB - Laravel needs ~64-128MB
opcache.interned_strings_buffer=16
; File system validation
opcache.validate_timestamps=0 ; In production, don't check file changes
; OR (if you deploy frequently)
opcache.validate_timestamps=1
opcache.revalidate_freq=60 ; Check every 60 seconds
; Max accelerated files (enough for Laravel)
opcache.max_accelerated_files=20000
; Memory efficiency
opcache.fast_shutdown=1
opcache.enable_file_override=0
opcache.optimization_level=0x7FFFBFFF
; JIT (PHP 8.0+)
opcache.jit=tracing
opcache.jit_buffer_size=100M
In production, set opcache.validate_timestamps=0 for maximum performance. But this means PHP will never see code changes until you restart PHP-FPM or clear OpCache.
Alternative: Set opcache.validate_timestamps=1 and opcache.revalidate_freq=60. This checks for file changes every 60 seconds.
Deployment best practice: Run php artisan opcache:clear or restart PHP-FPM after deployment.
JIT helps CPU-bound code, not I/O-bound code. Laravel apps are typically I/O-bound (database, Redis, API calls). For CRUD apps, JIT provides little benefit. For image processing, encryption, or complex calculations, JIT can be 3-5x faster.
; /etc/php/8.2/cli/conf.d/10-opcache.ini
[opcache]
; Enable OpCache (JIT requires OpCache)
opcache.enable=1
opcache.memory_consumption=256 ; JIT needs more memory
opcache.jit_buffer_size=100M ; JIT buffer (adjust based on app)
; JIT mode: tracing (recommended) or function
opcache.jit=tracing
; JIT optimization level (1205 is good default)
; 0 = disabled, 1-9 = more aggressive optimization
opcache.jit=1250
; Alternative JIT modes:
; opcache.jit=function ; JIT only function bodies
; opcache.jit=tracing ; JIT hot code paths (recommended)
; opcache.jit=disable ; No JIT
# Run this command
php -i | grep JIT
# Expected output:
# opcache.jit => tracing => tracing
# opcache.jit_buffer_size => 100M => 100M
| Operation | No OpCache | OpCache Only | OpCache + JIT | Improvement |
|---|---|---|---|---|
| Laravel home page (CRUD) | 65ms | 15ms | 14ms | 4.3x faster (JIT minimal help) |
| Image resize (CPU heavy) | 120ms | 115ms | 30ms | 4x faster (JIT helps) |
| Array sort (1M items) | 850ms | 840ms | 180ms | 4.7x faster (JIT helps) |
| Encryption (AES-256) | 45ms | 44ms | 12ms | 3.7x faster (JIT helps) |
For 90% of Laravel apps (CRUD, API, admin panels), JIT won't make a noticeable difference. The bottleneck is database, not CPU. Focus on indexes, caching, and query optimization first. Enable OpCache, then consider JIT if you have CPU-intensive operations.
# Check OpCache status
php -v # Shows if OpCache is enabled
# Clear OpCache (after deployment)
sudo systemctl restart php8.2-fpm
# Or using Artisan (if package installed)
composer require laravel/octane # Includes opcache:clear
php artisan opcache:clear
# Check OpCache statistics via web
# Create a route:
Route::get('/opcache-status', function () {
if (!app()->isLocal()) {
abort(404);
}
return '' . print_r(opcache_get_status(), true) . '
';
});
#!/bin/bash
# deploy.sh
php artisan down
git pull origin main
composer install --no-dev --optimize-autoloader
php artisan migrate --force
php artisan config:cache
php artisan route:cache
php artisan view:cache
# Clear OpCache so new code is compiled
sudo systemctl reload php8.2-fpm # Graceful reload
# OR
# sudo systemctl restart php8.2-fpm # Full restart (faster but kills active requests)
php artisan up
php -i | grep opcache.enableopcache.memory_consumptionopcache.max_accelerated_files (Laravel needs ~10,000)sudo systemctl reload php8.2-fpmopcache.enable=1 and opcache.jit_buffer_size > 0# Create a test file
echo '<?php var_dump(opcache_get_status(false));' | php
# Look for:
# ["opcache_enabled"]=> bool(true)
# ["memory_usage"]["used_memory"] => int(12345678)
# ["opcache_statistics"]["num_cached_scripts"] => int(342)
| Feature | Purpose | When to Enable | Performance Gain |
|---|---|---|---|
| OpCache | Cache compiled PHP opcodes | ALWAYS in production | 3-5x faster for PHP execution |
| OpCache + JIT (tracing) | Compile hot paths to machine code | CPU-intensive apps only | 3-5x faster for CPU operations |
| OpCache + JIT (function) | JIT entire functions | Very specific use cases | Variable |
Topic 18: Composer Autoloader Optimization — classmap-authoritative vs optimize-autoloader. How to make PHP stop searching for files and save 5-10ms per request.