PHP OPCache: The Secret Weapon for Laravel Performance Boost
OPCache, a built-in PHP opcode cache, is a powerful tool for significantly improving Laravel application speed. This guide will demonstrate how to effectively utilize OPCache to improve Laravel performance, decrease server load, and enhance overall application responsiveness.
Understanding OPCache
OPCache is a PHP extension designed to improve the performance of PHP scripts by storing precompiled script bytecode in shared memory. This eliminates the need for PHP to load and parse scripts on each request.
How OPCache Works
Compilation Cache: When a PHP script is executed, OPCache stores the compiled bytecode in memory.
Memory Storage: Subsequent requests for the same script are served from memory, avoiding disk I/O and compilation overhead.
Automatic Invalidation: OPCache automatically invalidates and recompiles scripts when changes are detected.
Benefits of Using OPCache
Reduced Load Times: Decreases the time needed to load and execute PHP scripts.
Lower CPU Usage: Reduces the CPU load by serving precompiled scripts.
Improved Scalability: Enhances the ability to handle more requests with the same server resources.
Cost Efficiency: Lowers server costs by optimizing resource usage.
Installing and Enabling OPCache
1. Install OPCache:
Make sure that OPCache is installed on your server. You can check this by listing all installed modules for your PHP setup using the command:
php --modules
If OPCache is not installed, you can do so by running the following command:
sudo apt install php8.x-opcache
Make sure to replace php8.x-opcache
with the appropriate version you are using, such as php8.3-opcache
.
2. Enable OPCache:
To configure OPCache via the php.ini
file, you can start by locating the php.ini
file, which is the main configuration file for PHP. The location of this file may vary depending on your server setup. You can find its location by running the following command:
php --ini
In our example, the file is located at:
/etc/php/8.3/cli/php.ini
Alternatively, you can create a separate configuration file specifically for OPCache settings, which is a common practice for keeping configurations organized. To do this, create a new file named 10-opcache.ini
in the conf.d
directory within your PHP configuration folder. This example assumes the directory is /etc/php/8.3/cli/conf.d/
.
In our example, the file is located at:
/etc/php/8.3/cli/conf.d/10-opcache.ini
The 10
prefix ensures the file is loaded in the correct order.
Now, add the following configurations to enable OPCache in your php.ini
file:
; Enable OPCache extension
zend_extension=opcache.so
; Recommended OPCache settings
opcache.enable=1
opcache.memory_consumption=128
opcache.interned_strings_buffer=8
opcache.max_accelerated_files=10000
opcache.revalidate_freq=2
opcache.fast_shutdown=1
opcache.enable_cli=1
opcache.validate_timestamps=1
opcache.file_cache=/path/to/cache
opcache.file_update_protection=2
opcache.max_wasted_percentage=5
Understanding OPCache Settings
Here are additional OPCache settings and what they mean:
opcache.enable=1
: Enables OPCache for PHP.opcache.memory_consumption=128
: Allocates 128MB of memory for storing precompiled scripts.opcache.interned_strings_buffer=8
: Allocates 8MB for interned strings in memory.opcache.max_accelerated_files=10000
: Sets the maximum number of files that can be cached.opcache.revalidate_freq=2
: Sets the frequency (in seconds) for checking script timestamps to see if they have been updated.opcache.fast_shutdown=1
: Enables fast shutdown to reduce memory usage when scripts are terminated.opcache.enable_cli=1
: Enables OPCache for the CLI version of PHP. This is useful for speeding up long-running PHP scripts executed from the command line.opcache.validate_timestamps=1
: When enabled, OPCache checks the timestamps of files to see if they have been updated. If a file is updated, it is recompiled. By default, it is enabled.opcache.file_cache=/path/to/cache
: Specifies the directory where OPCache should store cached scripts if they cannot be stored in shared memory.opcache.file_update_protection=2
: Ensures that cached scripts are not accessed until at least this many seconds have passed since they were last modified.opcache.max_wasted_percentage=5
: The percentage of "wasted" memory (due to fragmentation, etc.) that OPCache can tolerate before it triggers a restart of the cache to reclaim memory.
Configuring OPCache for Laravel
To optimize OPCache for Laravel, fine-tuning the configuration parameters is essential. Here are some recommended settings:
; Increase memory consumption to handle more scripts
opcache.memory_consumption=256
; Higher number of interned strings buffer for better performance
opcache.interned_strings_buffer=16
; Max number of scripts that can be cached
opcache.max_accelerated_files=20000
; Frequency of file status checks (in seconds)
opcache.revalidate_freq=60
; Enable file cache for scripts that can't be stored in shared memory
opcache.file_cache=/tmp
; Enable optimization for faster execution
opcache.opt_debug_level=0
Creating a Laravel Preload Script
Preloading allows you to load a set of PHP files into memory on startup, making them available for all requests. This can further reduce loading times for frequently used classes.
Step-by-Step Guide to Create a Preload Script
1. Create a Preload Script: Create a preload.php
file in the root of your Laravel application.
<?php
require_once __DIR__ . '/vendor/autoload.php';
class Preloader
{
private array $ignores = [];
private static int $count = 0;
private array $paths;
private array $fileMap;
public function __construct(string ...$paths)
{
$this->paths = $paths;
// We'll use composer's classmap
// to easily find which classes to autoload,
// based on their filename
$classMap = require __DIR__ . '/vendor/composer/autoload_classmap.php';
$this->fileMap = array_flip($classMap);
}
public function paths(string ...$paths): Preloader
{
$this->paths = array_merge(
$this->paths,
$paths
);
return $this;
}
public function ignore(string ...$names): Preloader
{
$this->ignores = array_merge(
$this->ignores,
$names
);
return $this;
}
public function load(): void
{
// We'll loop over all registered paths
// and load them one by one
foreach ($this->paths as $path) {
$this->loadPath(rtrim($path, '/'));
}
$count = self::$count;
echo "[Preloader] Preloaded {$count} classes" . PHP_EOL;
}
private function loadPath(string $path): void
{
// If the current path is a directory,
// we'll load all files in it
if (is_dir($path)) {
$this->loadDir($path);
return;
}
// Otherwise we'll just load this one file
$this->loadFile($path);
}
private function loadDir(string $path): void
{
$handle = opendir($path);
// We'll loop over all files and directories
// in the current path,
// and load them one by one
while ($file = readdir($handle)) {
if (in_array($file, ['.', '..'])) {
continue;
}
$this->loadPath("{$path}/{$file}");
}
closedir($handle);
}
private function loadFile(string $path): void
{
// We resolve the classname from composer's autoload mapping
$class = $this->fileMap[$path] ?? null;
// And use it to make sure the class shouldn't be ignored
if ($this->shouldIgnore($class)) {
return;
}
// Finally we require the path,
// causing all its dependencies to be loaded as well
require_once($path);
self::$count++;
echo "[Preloader] Preloaded `{$class}`" . PHP_EOL;
}
private function shouldIgnore(?string $name): bool
{
if ($name === null) {
return true;
}
foreach ($this->ignores as $ignore) {
if (strpos($name, $ignore) === 0) {
return true;
}
}
return false;
}
}
(new Preloader())
->paths(__DIR__ . '/vendor/laravel')
->ignore(
\Illuminate\Filesystem\Cache::class,
\Illuminate\Log\LogManager::class,
\Illuminate\Http\Testing\File::class,
\Illuminate\Http\UploadedFile::class,
\Illuminate\Support\Carbon::class,
)
->load();
2. Update PHP Configuration: Add the preload
script to your PHP configuration (php.ini
).
; Path to the preload script
opcache.preload=/path/to/your/laravel/project/preload.php
opcache.preload_user=www-data
3. Restart Web Server: After modifying the php.ini
file, restart your web server to apply the changes.
- For Apache:
sudo systemctl restart apache2
- For Nginx with PHP-FPM:
sudo systemctl restart php8.3-fpm
sudo systemctl restart nginx
Checking OPCache Status
To verify if OPCache is working as expected and to inspect preloading
details, create a PHP script named opcache.php
in your Laravel project's root directory with the following content:
<?php
$status = opcache_get_status();
print_r($status);
Run this script from the command line:
php opcache.php
The output will provide detailed information about OPCache usage, configuration, and preloaded scripts. Look for the statistics
section to verify preloading is working as intended.
Flushing OPCache
To clear the OPCache, you have two primary options:
1. Restart PHP or Web Server:
This is the most straightforward method to completely reset the OPCache.
However, it might disrupt ongoing requests.
2. Using a PHP Script:
Create a PHP script with the following content:
opcache_reset();
echo 'OPCache flushed successfully.';
Execute this script to clear the OPCache without restarting the server.
Monitoring OPCache
To ensure OPCache is functioning correctly and efficiently, you can monitor its performance using tools like opcache-gui
or opcache-status
.
Using opcache-gui
1. Install opcache-gui: Download and install opcache-gui from its GitHub repository.
git clone https://github.com/amnuts/opcache-gui.git /var/www/html/opcache-gui
2. Access opcache-gui: Open your browser and navigate to http://your-domain/opcache-gui
.
Using opcache-status
1. Install opcache-status: Download and install opcache-status from its GitHub repository.
git clone https://github.com/rlerdorf/opcache-status.git /var/www/html/opcache-status
2. Access opcache-status: Open your browser and navigate to http://your-domain/opcache-status
.
Additional Tips for Optimizing Laravel Performance
1. Config Caching: Cache your configuration files.
php artisan config:cache
2. Route Caching: Cache your routes to improve performance.
php artisan route:cache
3. View Caching: Pre-compile all Blade views.
php artisan view:cache
4. Optimize Composer Autoloader: Use optimized Composer autoloader.
composer dump-autoload --optimize
Performance Improvement with OPCache
By implementing OPCache and following these additional optimization tips, you can significantly boost the performance of your Laravel application. Here’s how OPCache improves performance:
Faster Load Times: By storing precompiled script bytecode in memory, OPCache reduces the time needed to load and execute PHP scripts, resulting in faster response times.
Reduced CPU Usage: Serving precompiled scripts directly from memory lowers CPU usage, as the server does not need to recompile scripts on each request.
Improved Scalability: With reduced load times and lower CPU usage, your Laravel application can handle more requests with the same server resources, improving scalability.
Enhanced Resource Utilization: Optimizing memory consumption and reducing wasted memory through OPCache settings helps in better resource management, leading to cost savings.
By leveraging OPCache and following best practices for Laravel performance optimization, you can ensure your application runs efficiently, providing a better user experience and reducing server costs.
.
🔥 Don't be left behind, get the Spec Coder VSCode Extension now
Please login or create new account to add your comment.