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?
2. How much slower is Xdebug in profiling mode?
3. What does pm.max_requests do in PHP-FPM?
Flashcards
Question
What does OPcache do?
Click to reveal answer
Answer
Caches compiled PHP bytecode in shared memory to avoid recompilation
Question
Xdebug impact in production?
Click to reveal answer
Answer
Disable it — 80-95% slower in profiling, 30-50% in debug mode
Question
How to calculate PHP-FPM max_children?
Click to reveal answer
Answer
available_memory / average_worker_memory
Question
Magento memory recommendation?
Click to reveal answer
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