DEV Community

ahmet gedik
ahmet gedik

Posted on

OPcache Optimization for PHP Applications

OPcache is PHP's built-in bytecode cache. It compiles PHP files once and stores the compiled bytecode in shared memory, eliminating the need to parse and compile on every request. Here's how to configure it properly, with lessons from running DailyWatch in production.

How OPcache Works

Without OPcache:

Request -> Read .php file -> Parse -> Compile to bytecode -> Execute
Enter fullscreen mode Exit fullscreen mode

With OPcache:

First request:  Read .php file -> Parse -> Compile -> Store in shared memory -> Execute
Next requests:  Load from shared memory -> Execute
Enter fullscreen mode Exit fullscreen mode

The parse and compile steps are skipped entirely for cached scripts.

Recommended Configuration

Add to your php.ini or .user.ini:

; Enable OPcache
opcache.enable=1
opcache.enable_cli=0

; Memory allocation
opcache.memory_consumption=128        ; 128MB for bytecode cache
opcache.interned_strings_buffer=16    ; 16MB for interned strings
opcache.max_accelerated_files=10000   ; Max cached scripts

; Revalidation
opcache.revalidate_freq=60            ; Check for file changes every 60s
opcache.validate_timestamps=1         ; Check if files changed (set to 0 in prod for max speed)

; Optimization
opcache.optimization_level=0x7FFEBFFF ; Enable all optimizations
opcache.save_comments=1               ; Keep doc comments (needed by some frameworks)
opcache.fast_shutdown=1               ; Use fast shutdown sequence

; JIT (PHP 8.0+)
opcache.jit=1255                      ; Tracing JIT
opcache.jit_buffer_size=64M           ; JIT code buffer
Enter fullscreen mode Exit fullscreen mode

Verifying OPcache Is Active

function checkOpcache(): void {
    if (!function_exists('opcache_get_status')) {
        echo "OPcache extension not loaded\n";
        return;
    }

    $status = opcache_get_status(false);

    if (!$status['opcache_enabled']) {
        echo "OPcache is disabled\n";
        return;
    }

    $memory = $status['memory_usage'];
    $stats = $status['opcache_statistics'];

    echo "OPcache Status:\n";
    echo "  Memory used: " . round($memory['used_memory'] / 1048576, 2) . " MB\n";
    echo "  Memory free: " . round($memory['free_memory'] / 1048576, 2) . " MB\n";
    echo "  Cached scripts: {$stats['num_cached_scripts']}\n";
    echo "  Hit rate: " . round($stats['opcache_hit_rate'], 2) . "%\n";
    echo "  Misses: {$stats['misses']}\n";
}
Enter fullscreen mode Exit fullscreen mode

Production vs Development Settings

// Development - prioritize seeing changes immediately
$devSettings = [
    'opcache.revalidate_freq' => 0,      // Always check for changes
    'opcache.validate_timestamps' => 1,   // File modification detection ON
];

// Production - prioritize performance
$prodSettings = [
    'opcache.revalidate_freq' => 300,     // Check every 5 minutes
    'opcache.validate_timestamps' => 0,    // Never check (requires manual reset)
];
Enter fullscreen mode Exit fullscreen mode

If validate_timestamps=0, you MUST reset OPcache after deploying new code:

// Call after deploy
opcache_reset();
Enter fullscreen mode Exit fullscreen mode

Cache Warming

Pre-compile your most-used files after a cache reset:

function warmOpcache(string $directory): int {
    $compiled = 0;
    $iterator = new RecursiveIteratorIterator(
        new RecursiveDirectoryIterator($directory)
    );

    foreach ($iterator as $file) {
        if ($file->getExtension() === 'php') {
            if (opcache_compile_file($file->getRealPath())) {
                $compiled++;
            }
        }
    }

    return $compiled;
}

// Warm after deploy
$count = warmOpcache('/var/www/html/app/');
echo "Pre-compiled {$count} PHP files\n";
Enter fullscreen mode Exit fullscreen mode

Performance Impact

Measured on dailywatch.video:

Metric Without OPcache With OPcache Improvement
Time to First Byte (uncached) 280ms 160ms 43% faster
PHP execution time 95ms 52ms 45% faster
Memory per request 4.2MB 2.8MB 33% less
Requests/sec (ab -n1000) 85 155 82% more

OPcache is the single easiest performance optimization you can make for a PHP application. It requires no code changes, just configuration. If you're running PHP in production without OPcache enabled, you're leaving significant performance on the table.

Check your current status with phpinfo() and configure accordingly. The defaults are intentionally conservative — tuning them for your specific application yields even better results.

Top comments (0)