Home Backend Development PHP7 Preloading (Opcache Preloading) in PHP 7.4

Preloading (Opcache Preloading) in PHP 7.4

Nov 30, 2019 pm 02:04 PM

In PHP 7.4, support for preloading was added, a feature that can significantly improve code performance.

In a nutshell, this is how it works:

● In order to preload the file, you need to write a custom PHP script

● This script starts on the server Executed once

● All preloaded files are available in memory for all requests

● Changes to preloaded files will have no impact until the server is restarted

Let’s understand it in depth.

#Opcache

Although preloading is built on top of opcache, it is not exactly the same. Opcache will take your PHP source files, compile them into "opcodes", and then store these compiled files on disk.

You can think of opcodes as low-level representations of code that are easily interpreted at runtime. Therefore, opcache skips the conversion step between the source file and what the PHP interpreter actually needs at runtime. A huge victory!

But we have more to gain. Opcached files don't know about other files. If class A extends from class B, they still need to be linked together at runtime. Additionally, opcache performs a check to see if the source file has been modified and will invalidate its cache based on this.

So, this is where preloading comes into play: it not only compiles source files into opcodes, but also links related classes, traits, and interfaces together. It then saves this "compiled" blob of runnable code (ie: code that the PHP interpreter can use) in memory.

Now when a request arrives at the server, it can use parts of the code base that are already loaded into memory without incurring any overhead.

So, what do we mean by "part of the code base"?

# Preloading in practice

In order to preload , the developer must tell the server which files to load. This was done with a simple PHP script and there was really nothing difficult about it.

The rules are simple:

● You provide a preload script and link it into your php.ini file using the opcache.preload command.

● Every PHP file you want to preload should be passed to opcache_compile_file(), or only once in the preloading script.

Suppose you want to preload a framework, such as Laravel. Your script must go through all the PHP files in the vendor/laravel directory and add them one after the other.

Link to this script in php.ini as follows:

opcache.preload=/path/to/project/preload.php
Copy after login

This is a dummy implementation:

$files = /* An array of files you want to preload */;
foreach ($files as $file) {
    opcache_compile_file($file);
}
Copy after login

# Warning: Unable to preload Linked classes

and so on, there is a warning! In order to preload files, their dependencies (interfaces, traits and parent classes) must also be preloaded.

If there are any issues with class dependencies, you will be notified when the server starts:

Can't preload unlinked class 
Illuminate\Database\Query\JoinClause: 
Unknown parent 
Illuminate\Database\Query\Builder
Copy after login

See, opcache_compile_file() will parse a file but not execute it. This means that if a class has dependencies that are not preloaded, it cannot be preloaded itself.

This is not a fatal problem and your server can work normally. But you won't get all the preloaded files you want.

Fortunately, there is a way to ensure that the linked file is also loaded: you can use require_once instead of opcache_compile_file and let the registered autoloader (probably composer's) take care of the rest.

$files = /* All files in eg. vendor/laravel */;
foreach ($files as $file) {
    require_once($file);
}
Copy after login

There are still some things to note. For example, if you try to preload Laravel, some classes in the framework depend on other classes that don't exist yet. For example, the filesystem cache class \lighting\filesystem\cache depends on \League\Flysystem\Cached\Storage\AbstractCache, and if you have never used filesystem cache, you may not be able to install it into your project.

You may encounter "class not found" errors when trying to preload everything. Fortunately, in a default Laravel installation, there are only a few of these classes and can be easily ignored. For convenience, I wrote a little preloader class to make ignoring files easier, like this:

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;
    }
}
Copy after login

By adding this class in the same preload script, we can now load like this The entire Laravel framework:

// …
(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();
Copy after login

# works?

This is of course the most important question: are all the files loaded correctly? You can test this simply by restarting the server and then dumping the output of opcache_get_status() into a PHP script . You'll see that it has a key called preload_statistics, which will list all preloaded functions, classes, and scripts; along with the memory consumed by the preloaded files.

# Composer Support

One promising feature could be the composer-based auto-preloading solution, which is already used by most modern PHP projects. People are working on adding a preload configuration option in composer.json which will generate the preload files for you! Currently, this feature is still under development, but you can follow it here.

#Server Requirements

There are two more important things to mention regarding devops when using preloading.

As you already know, you need to specify an entry in php.ini for preloading. This means that if you use shared hosting, you will not be able to configure PHP freely. In practice, you need a dedicated (virtual) server to be able to optimize preloaded files for individual projects. Remember this.

Also remember that you need to restart the server every time you need to reload the memory file (this is enough if using php-fpm). This may seem obvious to most people, but it's still worth mentioning.

#Performance

Now to the most important question: Does preloading really improve performance?

The answer is yes: Shared by Ben Morel Here are some benchmarks, which can be found in the same composer question linked previously.

Interestingly, you can decide to preload only "hot classes", which are classes that are frequently used in your code base. Ben's benchmarks show that loading only about 100 popular classes actually yields better performance gains than preloading all classes. This is the difference between a 13% and a 17% performance increase.

Of course, which classes should be preloaded depends on your specific project. It's wise to preload as much as possible at the beginning. If you do need a small percentage increase, you will have to monitor your code at runtime.

Of course, all of this work can be automated, and it may be possible in the future.

Now, the most important thing to remember is that composer will add support so that you don't have to make the preload files yourself, and it will be easy to set up this feature on your server as long as you have full control over it.

Translation: https://stitcher.io/blog/preloading-in-php-74

The above is the detailed content of Preloading (Opcache Preloading) in PHP 7.4. For more information, please follow other related articles on the PHP Chinese website!

Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

AI Hentai Generator

AI Hentai Generator

Generate AI Hentai for free.

Hot Article

R.E.P.O. Energy Crystals Explained and What They Do (Yellow Crystal)
2 weeks ago By 尊渡假赌尊渡假赌尊渡假赌
Repo: How To Revive Teammates
4 weeks ago By 尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island Adventure: How To Get Giant Seeds
3 weeks ago By 尊渡假赌尊渡假赌尊渡假赌

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

Which versions of PHP7 have introduced new operators Which versions of PHP7 have introduced new operators Mar 03, 2025 pm 04:37 PM

This article details PHP 7's new operators: the null coalescing (??), spaceship (<=>), and null coalescing assignment (??=) operators. These enhance code readability and performance by simplifying null checks and comparisons, indirectl

How to optimize PHP7 code to improve performance How to optimize PHP7 code to improve performance Mar 03, 2025 pm 04:28 PM

This article examines optimizing PHP7 code for performance. It addresses common bottlenecks like inefficient database queries, I/O operations, and memory leaks. Solutions include efficient coding practices, database & caching strategies, asynch

What are the impacts of different versions of PHP7 on memory consumption What are the impacts of different versions of PHP7 on memory consumption Mar 03, 2025 pm 04:35 PM

PHP 7's minor version differences yield subtle memory consumption variations. While newer versions generally improve performance and memory efficiency via Zend Engine and garbage collection optimizations, the impact is application-dependent. Signif

How to Use Sessions Effectively in PHP 7? How to Use Sessions Effectively in PHP 7? Mar 10, 2025 pm 06:20 PM

This article details effective PHP 7 session management, covering core functionalities like session_start(), $_SESSION, session_destroy(), and secure cookie handling. It emphasizes security best practices including HTTPS, session ID regeneration, s

How to Upgrade from PHP 5.6 to PHP 7? How to Upgrade from PHP 5.6 to PHP 7? Mar 10, 2025 pm 06:29 PM

This article details upgrading PHP 5.6 to PHP 7, emphasizing crucial steps like backing up, checking server compatibility, and choosing an upgrade method (package manager, compiling, control panel, or web server configuration). It addresses potentia

What bugs have been fixed in the PHP7 version update What bugs have been fixed in the PHP7 version update Mar 03, 2025 pm 04:36 PM

PHP 7 significantly improved upon previous versions by addressing numerous bugs, enhancing performance, and bolstering security. Key improvements included a rewritten Zend Engine 3, optimized memory management, and refined error handling. While gene

How to Monitor PHP 7 Performance with Tools like New Relic? How to Monitor PHP 7 Performance with Tools like New Relic? Mar 10, 2025 pm 06:28 PM

This article explains how to monitor PHP 7 application performance using New Relic. It details New Relic's setup, key performance indicators (KPIs) like Apdex score and response time, bottleneck identification via transaction traces and error track

What impact does the PHP7 version update have on session processing? What impact does the PHP7 version update have on session processing? Mar 03, 2025 pm 04:31 PM

This article examines session handling in PHP7, highlighting performance improvements stemming from the enhanced Zend Engine. It discusses potential compatibility issues from upgrading and details optimization strategies for security and scalability

See all articles