Zend OpCache for PHP
PHP is a powerful scripting language that powers a significant portion of the web. To enhance its performance, PHP can utilize Zend Opcode Cache (often referred to as Opcache). This article provides an overview of Zend Opcache, its benefits, how it works with PHP handlers, its expiration mechanisms, troubleshooting, monitoring, and tuning tips to help you get the most out of your PHP applications.
What is Zend opcode cache?
When a PHP script is executed, the PHP engine first compiles the human-readable code into a low-level intermediate representation called “opcodes.” Zend Opcode Cache is a PHP extension that improves performance by storing these precompiled script bytecodes in shared memory. This process eliminates the need for PHP to load and parse scripts on each request, significantly speeding up execution time.
Here’s a simplified breakdown of how it works:
- First Request: When a PHP script is requested for the first time, PHP reads the file, compiles it into opcodes, and then executes these opcodes. If Opcache is enabled, it stores these opcodes in shared memory.
- Subsequent Requests: For any following requests to the same script, PHP can directly retrieve the precompiled opcodes from shared memory and execute them. This now bypasses the relatively slow steps of reading the script from disk and compiling it.
Performance benefits
Enabling Zend Opcache offers several performance advantages:
- Faster Response Times: By skipping the compilation step, PHP scripts execute much faster, leading to quicker page load times for your website visitors.
- Reduced Server Load: Since the CPU doesn’t have to recompile PHP scripts on every request, the overall server load (CPU usage and I/O operations) is reduced. This allows your server to handle more traffic efficiently.
- Improved Scalability: With lower resource consumption per request, your application can scale more effectively to accommodate a growing number of users.
PHP handler requirements for Opcache
For Zend Opcache to effectively maintain a cache of opcodes, the PHP handler you use must support a persistent parent process that can manage this shared memory across multiple requests. Common PHP handlers that work well with Opcache include:
- PHP-FPM (FastCGI Process Manager): This is a highly recommended PHP handler for performance and scalability. PHP-FPM’s master process manages worker processes, and the Opcache shared memory is maintained effectively.
- FastCGI: Apache’s
mod_fcgidstarts up a certain amount of persistent processes that listen for new PHP requests and process them when needed. - mod_php (DSO – Dynamic Shared Object for Apache): When PHP runs as an Apache module, Opcache can be used. The shared memory is typically initialized when the Apache parent process starts. The downside is DSO is less secure than FastCGI or PHP-FPM, especially on shared environments with many websites.
Handlers like SuPHP or CGI, which execute PHP scripts as separate processes for each request and terminate afterward, cannot effectively maintain a persistent opcode cache in shared memory. While Opcache might technically be enabled, its benefits will be minimal as the cache would be created and destroyed with each request.
Opcache expiration and revalidation
It’s crucial that Opcache serves the latest version of your PHP files, especially during development or after deploying updates. Opcache handles this through a few key mechanisms and configuration directives:
opcache.validate_timestamps(Default:1– enabled):- When enabled (set to
1), Opcache checks the modification timestamp of your PHP files periodically to see if they have changed. - If a file has been modified, Opcache will invalidate the old cached opcode and recompile the new version of the script.
- When disabled (set to
0), Opcache will not check for updates after the initial caching. You would need to manually reset Opcache (e.g., by restarting the web server or callingopcache_reset()) for changes to take effect. This is generally recommended for production environments for maximum performance, assuming you have a deployment process that clears the Opcache.
- When enabled (set to
opcache.revalidate_freq(Default:2seconds):- This directive specifies how often (in seconds) Opcache should check the script’s timestamp for updates, but only if
opcache.validate_timestampsis enabled. - A value of
0means Opcache will check on every request, which can add overhead. Higher values reduce the checking frequency but mean there’s a delay before changes to files are reflected. - The default value of 2 seconds is generally fine, as opcache being at most 2 seconds out of date is considered acceptable by most.
- This directive specifies how often (in seconds) Opcache should check the script’s timestamp for updates, but only if
Manually clearing the Opcache can be done by restarting the web server (Apache, Nginx) or the PHP-FPM service. You can also use PHP functions like opcache_reset() in a script, though this requires careful security considerations if exposed via the web.
Troubleshooting common issues
While Opcache is generally stable, you might encounter a few common issues:
- Changes Not Reflecting:
- Cause: This is the most common issue, especially in production environments where
opcache.validate_timestampsmight be disabled for performance. - Solution: If
opcache.validate_timestampsis disabled, you must manually clear the Opcache after deploying new code. This can be done by restarting your web server or PHP-FPM service, or by using a script that callsopcache_reset(). Ifopcache.validate_timestampsis enabled, ensureopcache.revalidate_freqis set to a reasonable value for your environment.
- Cause: This is the most common issue, especially in production environments where
- Cache Full or High Eviction Rate:
- Cause: The allocated memory for Opcache (
opcache.memory_consumption) is insufficient for the number or size of your PHP scripts, or the maximum number of files (opcache.max_accelerated_files) is too low. This leads to frequently used scripts being evicted from the cache and then recompiled. - Solution: Increase
opcache.memory_consumptionand/oropcache.max_accelerated_filesin yourphp.inior Opcache configuration file. Monitor the Opcache status (see next section) to find optimal values.
- Cause: The allocated memory for Opcache (
- “Cannot redeclare class” Errors:
- Cause: This can sometimes occur due to how Opcache handles file includes or naming collisions, especially if
opcache.use_cwdis disabled in an environment where it’s needed. - Solution: Ensure
opcache.use_cwd = 1if you have scripts with identical names in different directories that might be included. In rare cases, theopcache.dups_fixdirective might be needed, but this is generally for older or very specific edge cases.
- Cause: This can sometimes occur due to how Opcache handles file includes or naming collisions, especially if
Monitoring opcache via phpinfo()
The easiest way to check if Opcache is enabled and to see its current configuration and statistics is by using the phpinfo() function. Create a PHP file (e.g., info.php) in your web directory with the following content:
<?php
phpinfo();
?>Access this file through your web browser. Scroll down to find a section titled “Zend OPcache” (or simply “opcache”). Here you will find:
- Opcache enabled: Whether Opcache is active (Up and Running).
- Cache full: Indicates if the allocated memory is full.
- Memory usage:
used_memory: Amount of memory currently used.free_memory: Amount of memory still available.wasted_memory: Memory that is allocated but not usable (fragmentation). A high wasted percentage might indicate the need for a restart or tuning.
- Interned strings usage: Similar memory statistics for interned strings.
- Opcache statistics:
num_cached_scripts: Number of scripts currently in the cache.num_cached_keys: Number of keys used in the Opcache hash table (related tomax_accelerated_files).max_cached_keys: The configured value foropcache.max_accelerated_files.hits: Number of times a cached opcode was successfully retrieved.misses: Number of times a script had to be compiled because it wasn’t in the cache.opcache_hit_rate: Percentage of cache hits. A high hit rate (e.g., >99%) is desirable.
- Directives: All the Opcache configuration directives and their current values (local and master).
Regularly checking this output can help you understand how well Opcache is performing and if any tuning is necessary.
We recommend removing your phpinfo file once you are done using it, as it can expose sensitive server details such as software versions and file paths, and system usernames.
Tuning Opcache settings
You can fine-tune Opcache through various directives in your php.ini file or specific Opcache configuration files (e.g., opcache.ini). Restart your web server or PHP-FPM service after making changes.
Here are some key directives for tuning:
Core settings
opcache.enable(Default:1) Set to1to enable Opcache,0to disable. It’s usually enabled by default in modern PHP versions. Can only be disabled at runtime viaini_set(), not enabled.opcache.memory_consumption(Default:128MB) The size of the shared memory storage used by Opcache, in megabytes. The optimal value depends on the total size of your application’s PHP codebase. If yourphpinfo()shows the cache is often full or the hit rate is low due to evictions, you should increase this. Common values range from 64MB to 512MB or more for large applications.opcache.interned_strings_buffer(Default:8MB) The amount of memory used to store interned strings, in megabytes. PHP uses string interning to improve performance by storing identical strings only once. For applications with many unique strings (common in large frameworks), increasing this (e.g., to 16MB, 32MB, or 64MB) can improve performance and reduce overall memory usage. Monitor “Interned Strings Usage” inphpinfo().opcache.max_accelerated_files(Default:10000) The maximum number of scripts (PHP files) that can be stored in the Opcache. If you have more PHP files in your project(s) than this number, Opcache might not be able to cache all of them, leading to cache misses. You can count the number of.phpfiles in your project to get an estimate. The value must be between 200 and 1,000,000.
Revalidation settings (important for production vs. development)
opcache.validate_timestamps(Default:1) As discussed earlier, set to1(enabled) for development so Opcache checks for file changes. For production, set to0(disabled) for maximum performance, and ensure you have a process to clear Opcache during deployments (e.g., restarting PHP-FPM or usingopcache_reset()).opcache.revalidate_freq(Default:2seconds) How often (in seconds) to check script timestamps for updates ifopcache.validate_timestampsis enabled. Ignored ifopcache.validate_timestampsis0. Raise this if you don’t plan on frequently updating your php files. You can always lower it prior to making changes so they show up quickly.
Other useful settings
opcache.save_comments(Default:1) If set to1(enabled), PHPDoc comments are kept in the cache. Disabling this (0) can save a small amount of memory but might break applications or frameworks that rely on parsing docblocks at runtime (e.g., for annotations).opcache.enable_cli(Default:0) Set to1to enable Opcache for the Command Line Interface (CLI) version of PHP. This can speed up PHP scripts run from the command line, such as cron jobs or build tools. However, ensure it doesn’t cause issues with frequently changing CLI scripts if timestamps aren’t validated frequently for CLI.opcache.max_wasted_percentage(Default:5%) The maximum percentage of “wasted” memory allowed before a restart of the cache is scheduled (if there’s not enough free memory). Wasted memory occurs due to outdated scripts. If this threshold is reached, Opcache might restart, clearing all cached opcodes. Increasing this slightly (e.g., to10or15) might be beneficial if you see too many OOM (Out Of Memory) restarts, but generally, ensuring sufficientopcache.memory_consumptionis the better approach.
Finding the optimal Opcache settings often involves monitoring your application’s behavior using phpinfo() or other monitoring tools and adjusting values based on the statistics (hit rate, memory usage, number of cached scripts). Start with reasonable defaults, monitor, and then tune incrementally.
By understanding and properly configuring Zend Opcache, you can significantly enhance the performance and efficiency of your PHP applications hosted with Liquid Web.