As of now OPcache cannot be statically compiled into the PHP binary at all, which is the direct opposite from what we are proposing. This is due to an incompatibility between JIT and ZTS builds. Arnaud has prepared a proof-of-concept implementation fixing this issue at: [RFC][PoC] Allow opcache to be built statically by arnaud-lb · Pull Request #18660 · php/php-src · GitHub. The changes in that PR would also allow building static PHP binaries with OPcache enabled in the first place (e.g. for use with FrankenPHP).
I really like the idea. We use the Embed SAPI statically linked and at the moment we need to take great care to bundle the OPcache extension. This will make it a lot easier for us. A big +1 from my point of view!
Regards,
Michael
Tim Düsterhus <tim@bastelstu.be> schrieb am Mo. 26. Mai 2025 um 12:49:
Hi
Arnaud, Ilija and I would like to propose making OPcache a non-optional
part of PHP starting with PHP 8.5.
As of now OPcache cannot be statically compiled into the PHP binary at
all, which is the direct opposite from what we are proposing. This is
due to an incompatibility between JIT and ZTS builds. Arnaud has
prepared a proof-of-concept implementation fixing this issue at: https://github.com/php/php-src/pull/18660. The changes in that PR would
also allow building static PHP binaries with OPcache enabled in the
first place (e.g. for use with FrankenPHP).
As of now OPcache cannot be statically compiled into the PHP binary at
all, which is the direct opposite from what we are proposing. This is
due to an incompatibility between JIT and ZTS builds. Arnaud has
prepared a proof-of-concept implementation fixing this issue at: [RFC][PoC] Allow opcache to be built statically by arnaud-lb · Pull Request #18660 · php/php-src · GitHub. The changes in that PR would
also allow building static PHP binaries with OPcache enabled in the
first place (e.g. for use with FrankenPHP).
Best regards
Tim Düsterhus
I cannot speak to the implementation details, but I am fully on board with the intent and goal here. +1.
As of now OPcache cannot be statically compiled into the PHP binary at all, which is the direct opposite from what we are proposing. This is due to an incompatibility between JIT and ZTS builds. Arnaud has prepared a proof-of-concept implementation fixing this issue at: [RFC][PoC] Allow opcache to be built statically by arnaud-lb · Pull Request #18660 · php/php-src · GitHub. The changes in that PR would also allow building static PHP binaries with OPcache enabled in the first place (e.g. for use with FrankenPHP).
Best regards
Tim Düsterhus
The RFC states:
> `zend_extension=opcache` will need to be removed from a user’s php.ini
> configuration
Is this really a *need*, or is it more of a recommendation? If it's left in a user's configuration, what is the impact?
OPcache being a non-optional part of PHP and always being loaded does not
mean that OPcache functionality is always active. This RFC specifically
does not propose the removal of the existing INI settings, such as
opcache.enable or opcache.enable_cli.
To me, being able to turn off opcache defeats the purpose of putting it into
core. In fact, take this part of the RFC's introduction:
As an example, OPcache needs to explicitly be compiled and loaded when
using the PHP “Docker Official Image”, making it easy for users to
accidentally run without OPcache when using Docker. Furthermore OPcache
being optional and just “hooking” into the engine also means that there are
two entirely separate code-paths for core PHP functionality (such as
loading and compiling a PHP script), which can easily result in
OPcache-specific bugs (such as #17422) that are hard to detect during
testing.
If opcache can still be disabled, and isn't enabled by default in CLI, then
in practice we still have all of these issues. The engine may not have to
care about "is opcache around?" but it still has to care "is opcache
enabled?" Dropping the first part isn't that helpful if the second part still
has to be asked.
To me, being able to turn off opcache defeats the purpose of putting it into
core. In fact, take this part of the RFC's introduction:
Part of this is, at least to me, that "turning off" OpCache is not a binary things: bytecode caching on/off, bytecode optimization on/off, JIT on/off, ...
Indeed. To explain further: The `opcache.so` will no longer exist, thus the behavior is as with any other non-existent extension you are trying to load.
You can already try yourself with `php -dzend_extension=does-not-exist.so`
If opcache can still be disabled, and isn't enabled by default in CLI, then
in practice we still have all of these issues. The engine may not have to
care about "is opcache around?" but it still has to care "is opcache
enabled?" Dropping the first part isn't that helpful if the second part still
has to be asked.
Sebastian's response is quite accurate. While it is true that it will still be necessary to test the different code-paths, there is no single thing “OPcache”. It is rather a collection of assorted features that need to integrate into the engine by hooking into a small number of hooks (replacing some function pointers). By allowing a tighter integration with the engine, the OPcache-specific logic can be guarded by simple `if (caching_enabled)` or `if (optimizer_enabled)` statements, allowing a more direct data flow by means of local variables instead of being restricted to some kind of “middleware-style” wrapping of the original logic, possibly duplicating some of it by copy and paste. By having the entire logic in a single place it also becomes easier to see if it would be necessary to make some changes to the caching when modifying the compilation, this is also true for a code reviewer might be able to point out logic mistakes more easily. And of course in the future some of the `if()` statements might also be removed entirely when it turns out that the logic guarded by them does not have any drawbacks or the default values of INI settings can be updated.
Long story short: By integrating OPcache directly into the engine, we can only gain some maintenance flexibility. In the worst case, we are in no worse situation than currently and it can only get better from there.
And of course there's also the benefits to the users of PHP, since less configuration will be required for a production set-up. If OPcache is always loaded, it means that it will also be enabled by default for FPM set-ups, since `opcache.enable` defaults to `1`.
Best regards
Tim Düsterhus
PS: Did you know that OPcache can optionally replace (opcache.enable_file_override) the implementation for the `file_exists()` function, amongst others? I did not until recently.
For people installing PHP from .deb or .rpm sources this shouldn’t be an issue either way as the package managers would take care of that (no more opcache extension, no opcache.ini).
For the rest, and to avoid a lot of startup warnings we could consider to explicitly ignore loading of a zend_extension=opcache? Technically this should be easy but the question is if this is sensible.
People could have an custom extension named opcache.so that does something else, but that feels very unlikely.
Otherwise, massive fan of the RFC. Having opcache as a given (even if deactivated) will make it a lot easier to get people to use it and reduce friction.