Help Docs Performance Website Optimization Zend OpCache for PHP

Zend OpCache for PHP

Learn to boost PHP speed with Zend Opcache.

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:

  1. 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.
  2. 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_fcgid starts 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 calling opcache_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.
  • opcache.revalidate_freq (Default: 2 seconds):
    • This directive specifies how often (in seconds) Opcache should check the script’s timestamp for updates, but only if opcache.validate_timestamps is enabled.
    • A value of 0 means 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.

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_timestamps might be disabled for performance.
    • Solution: If opcache.validate_timestamps is 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 calls opcache_reset(). If opcache.validate_timestamps is enabled, ensure opcache.revalidate_freq is set to a reasonable value for your environment.
  • 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_consumption and/or opcache.max_accelerated_files in your php.ini or Opcache configuration file. Monitor the Opcache status (see next section) to find optimal values.
  • “Cannot redeclare class” Errors:
    • Cause: This can sometimes occur due to how Opcache handles file includes or naming collisions, especially if opcache.use_cwd is disabled in an environment where it’s needed.
    • Solution: Ensure opcache.use_cwd = 1 if you have scripts with identical names in different directories that might be included. In rare cases, the opcache.dups_fix directive might be needed, but this is generally for older or very specific edge cases.

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 to max_accelerated_files).
    • max_cached_keys: The configured value for opcache.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.

Warning

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 to 1 to enable Opcache, 0 to disable. It’s usually enabled by default in modern PHP versions. Can only be disabled at runtime via ini_set(), not enabled.
  • opcache.memory_consumption (Default: 128 MB) 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 your phpinfo() 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: 8 MB) 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” in phpinfo().
  • 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 .php files 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 to 1 (enabled) for development so Opcache checks for file changes. For production, set to 0 (disabled) for maximum performance, and ensure you have a process to clear Opcache during deployments (e.g., restarting PHP-FPM or using opcache_reset()).
  • opcache.revalidate_freq (Default: 2 seconds) How often (in seconds) to check script timestamps for updates if opcache.validate_timestamps is enabled. Ignored if opcache.validate_timestamps is 0. 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 to 1 (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 to 1 to 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., to 10 or 15) might be beneficial if you see too many OOM (Out Of Memory) restarts, but generally, ensuring sufficient opcache.memory_consumption is 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.

Was this article helpful?