Skip to content
intermediate Phase 11 · PHP Engineering Practices

PHP Performance Optimization

OPcache, memory management, profiling, Xdebug impact, PHP-FPM tuning, and performance considerations for Magento

45m
0 problems
Topic Progress 0%

OPcache Configuration

What is OPcache?

OPcache pre-compiles PHP scripts into bytecode and stores them in shared memory, eliminating the need to compile on each request.

Optimal Configuration

; php.ini settings
opcache.enable=1
opcache.enable_cli=1

; Memory allocation
opcache.memory_consumption=256        ; MB for compiled scripts
opcache.interned_strings_buffer=16     ; MB for interned strings
opcache.max_accelerated_files=20000    ; Max number of scripts to cache

; Revalidation
opcache.revalidate_freq=0              ; Check for changes every request (dev)
opcache.revalidate_freq=60             ; Check every 60 seconds (production)

; Performance
opcache.save_comments=1                ; Required for Magento annotations
opcache.enable_file_override=1         ; Skip stat() if file not modified
opcache.max_wasted_percentage=5        ; Max wasted memory before restart

; JIT (PHP 8.0+)
opcache.jit=1255                       ; Trigger-based JIT
opcache.jit_buffer_size=128M           ; JIT buffer size

OPcache Impact

// Without OPcache: ~50ms per request (compilation)
// With OPcache:   ~5ms per request (bytecode from memory)
// 10x improvement just from OPcache

Verify OPcache

// Check OPcache status
php -r "print_r(opcache_get_status());"

// Check cached scripts
php -r "print_r(opcache_get_status()['opcache_statistics']);"

For Magento, always verify OPcache is enabled in production. A single bin/magento setup:di:compile with OPcache off wastes significant time.

Memory Management & Profiling

Memory Management

// Check memory usage
$memBefore = memory_get_usage();
$memPeak = memory_get_peak_usage();

// Process large dataset efficiently
$collection = $this->productCollection->addFieldToSelect('*');

// BAD: Load all at once (high memory)
$products = $collection->load(); // All products in memory

// GOOD: Iterate in chunks
$collection->setPageSize(100);
$currentPage = 1;
while ($currentPage <= $collection->getLastPageNumber()) {
    $collection->setCurPage($currentPage);
    foreach ($collection as $product) {
        $this->process($product);
    }
    $collection->clear(); // Free memory
    $currentPage++;
}

// Or use generator for memory efficiency
function getProducts(): \Generator
{
    $collection = $this->productCollection->setPageSize(100);
    for ($page = 1; $page <= $collection->getLastPageNumber(); $page++) {
        $collection->setCurPage($page);
        foreach ($collection as $product) {
            yield $product;
        }
    }
}

Profiling with Xdebug

// Enable profiling (BEWARE: massive performance impact)
// xdebug.mode=profile
// xdebug.output_dir=/tmp/xdebug

// Manual profiling for specific sections
xdebug_start_trace('/tmp/trace');
$this->heavyOperation();
xdebug_stop_trace();
// Analyze with CacheGrind or WebGrind

Xdebug Performance Impact

Mode Impact
xdebug.mode=off No impact
xdebug.mode=debug 30-50% slower
xdebug.mode=profile 80-95% slower
xdebug.mode=trace 95%+ slower

Always disable Xdebug in production and during setup:di:compile.

# Compile without Xdebug (10x faster)
php -d xdebug.mode=off bin/magento setup:di:compile

# Or use PHP CLI without extensions
php -n bin/magento setup:di:compile

PHP-FPM Tuning for Magento

PHP-FPM Configuration

; /etc/php/8.1/fpm/pool.d/www.conf

; Process management
pm = dynamic
pm.max_children = 50          ; Max worker processes
pm.start_servers = 10         ; Processes to start
pm.min_spare_servers = 5      ; Min idle processes
pm.max_spare_servers = 20     ; Max idle processes
pm.max_requests = 1000        ; Restart workers after N requests (memory leak prevention)

; Timeouts
request_terminate_timeout = 180 ; Kill worker after 3 minutes
request_slowlog_timeout = 5     ; Log slow requests

; Memory
php_admin_value[memory_limit] = 756M ; Magento recommends 756M+

Calculating pm.max_children

available_memory = server_RAM - OS_overhead - MySQL - Other_services
max_children = available_memory / average_worker_memory

Typical Magento worker: 150-300MB
For 8GB server: 6GB available / 200MB = 30 workers

Magento-Specific Performance

// 1. Full-page cache (Varnish/Redis)
// Reduces PHP execution by serving cached pages

// 2. Magento compilation
bin/magento setup:di:compile  // Generates proxies, factories, interceptors
bin/magento setup:static-content:deploy  // Deploys static assets

// 3. Redis for sessions and cache
// app/etc/env.php
'cache' => [
    'frontend' => [
        'default' => [
            'backend' => 'Magento\Framework\Cache\Backend\Redis',
            'backend_options' => [
                'server' => '127.0.0.1',
                'port' => '6379',
            ],
        ],
    ],
],

// 4. Elasticsearch/OpenSearch for search (not MySQL)

// 5. Asynchronous operations (message queue)
// Offload email, inventory sync, indexing to queues

Quiz

1. What is the primary benefit of OPcache?

Question 1 options

2. How much slower is Xdebug in profiling mode?

Question 2 options

3. What does pm.max_requests do in PHP-FPM?

Question 3 options

Flashcards

Question

What does OPcache do?

Answer

Caches compiled PHP bytecode in shared memory to avoid recompilation

Question

Xdebug impact in production?

Answer

Disable it — 80-95% slower in profiling, 30-50% in debug mode

Question

How to calculate PHP-FPM max_children?

Answer

available_memory / average_worker_memory

Question

Magento memory recommendation?

Answer

756M+ PHP memory limit

Revision Notes

Key Takeaways

  • 1. OPcache: enable in production, provides ~10x improvement
  • 2. Xdebug: always disable in production, massive performance impact
  • 3. PHP-FPM: tune pm.max_children based on available memory
  • 4. Memory: process collections in pages, not all at once
  • 5. Magento: use Varnish, Redis, Elasticsearch, and async queues

Interview Tips

  • Explain OPcache: what it caches, how it improves performance
  • Discuss Xdebug's impact and when to use each mode
  • Give Magento-specific optimizations: compilation, caching, async

Cheat Sheet

OPcache: memory=256M, files=20000, revalidate_freq=60
Xdebug: DISABLE in production (80-95% slower)
PHP-FPM: max_children = available_RAM / worker_memory
Magento: 756M+ memory, Redis, Varnish, Elasticsearch

Profiling:
  memory_get_usage() / memory_get_peak_usage()
  xdebug_start_trace() / xdebug_stop_trace()

Compile faster: php -d xdebug.mode=off bin/magento setup:di:compile