Both sides previous revisionPrevious revisionNext revision | Previous revisionNext revisionBoth sides next revision |
rfc:opcache.no_cache [2020/05/16 16:38] – tandre | rfc:opcache.no_cache [2020/06/13 14:37] – RFC was declined tandre |
---|
====== PHP RFC: Opcache optimization without any caching ====== | ====== PHP RFC: Opcache optimization without any caching ====== |
* Version: 0.1 | * Version: 0.4 |
* Date: 2020-05-16 (use today's date here) | * Date: 2020-05-16 |
* Author: Tyson Andre <tandre@php.net> | * Author: Tyson Andre <tandre@php.net> |
* Status: Under Discussion | * Status: Declined |
* Implementation: https://github.com/php/php-src/pull/5504 | * Implementation: https://github.com/php/php-src/pull/5504 |
* First Published at: https://wiki.php.net/rfc/opcache.no_cache | * First Published at: https://wiki.php.net/rfc/opcache.no_cache |
Currently, it isn't possible to enable optimizations without enabling caching. | Currently, it isn't possible to enable optimizations without enabling caching. |
They should be orthogonal features - it's already possible to cache without | They should be orthogonal features - it's already possible to cache without |
optimization passes (''opcache.optimization_level=0'') | optimization passes by setting ''opcache.optimization_level=0''. |
| |
Users either have to enable shared memory caching, or ''opcache.file_cache_only''. Doing that has the following drawbacks: | Without the feature being proposed, users would either have to enable shared memory caching, or ''opcache.file_cache_only''. Doing that has the following drawbacks: |
| |
* For ''opcache.file_cache_only'', users would be forced to manage the file cache. The end users of an application using ''opcache.file_cache_only'' may be unfamiliar with opcache. \\ (Enabling ''opcache.file_cache_only'' could lead to issues such as running out of disk space, needing to clear stale entries, concerns about opcode corruption not being fixed after restarting a process or computer, etc) | * For ''opcache.file_cache_only'', users would be forced to manage the file cache. The end users of an application using ''opcache.file_cache_only'' may be unfamiliar with opcache. \\ (Enabling ''opcache.file_cache_only'' could lead to issues such as running out of disk space, needing to clear stale entries, concerns about opcode corruption not being fixed after restarting a process or computer, etc) |
===== Proposal ===== | ===== Proposal ===== |
| |
Make the opcode optimizer and JIT available without opcode caching, through a new setting ''opcache.no_cache''. | Make the opcode optimizer and JIT available without opcode caching, through a new setting ''opcache.allow_cache''. |
| |
==== Use Cases ==== | ==== Use Cases ==== |
| |
''opcache.no_cache'' is useful when there isn't much available memory and/or there are multiple long-lived php scripts managed by something that is not a php script. | ''opcache.allow_cache=0'' is useful when there isn't much available memory and/or there are multiple long-lived php scripts managed by something that is not a php script. |
| Some example use cases are: |
| |
* ''supervisord'' managing hundreds of long-lived PHP CLI processes | * ''supervisord'' managing hundreds of long-lived PHP CLI processes. |
* Tools that run in the background in IDEs for end users of PHP. (Especially if they are long-lived, large applications that don't use ''pcntl_fork'') | * Tools that run in the background in IDEs for end users of PHP. (Especially if they are long-lived, large applications that don't use ''pcntl_fork'') |
| * Long-lived CLI Web Servers where a single CLI process serves many different requests (e.g. [[https://reactphp.org/http/|ReactPHP's HTTP Server]]) |
| |
Even when barely any files are run, the virtual memory to track the shared memory segment seems to add 2MB extra per **independent** php process in "shared memory" segments, reducing the free RAM available for other processes. \\ (starting a large number of php CLI scripts that ''sleep()'' in a loop, ''free'' (Linux program to report free memory) reports that ''shared'' (shared memory) increases by 2MB per process without ''opcache.no_cache'', but barely increases with ''opcache.no_cache=1''. This will vary on different systems, and will use up more memory if many php files are loaded. | Even when barely any files are run, the virtual memory to track the shared memory segment seems to add 2MB extra per **independent** php process in "shared memory" segments, reducing the free RAM available for other processes. \\ (starting a large number of php CLI scripts that ''sleep()'' in a loop, ''free'' (Linux program to report free memory) reports that ''shared'' (shared memory) increases by 2MB per process with the default (''opcache.allow_cache=1''), but barely increases with ''opcache.allow_cache=0''. This will vary on different systems, and will use up more memory if many php files are loaded. |
| |
''opcache.no_cache'' is **not** intended for running web servers (e.g. ''apache''), where PHP would share a common memory address space (it would almost always be better to cache when optimizations are enabled). | ''opcache.allow_cache=0'' is **not** intended for running web servers (e.g. ''apache''), where PHP would share a common memory address space (it would almost always be better to cache when optimizations are enabled). |
| |
''opcache.no_cache'' is also **not** intended for extremely short-lived CLI processes (Opcode optimization may be more time-consuming than the program being run, making the file_cache or ''opcache.enable_cli=0'' a better choice). | ''opcache.allow_cache=0'' is also **not** intended for extremely short-lived CLI processes (Opcode optimization may be more time-consuming than the program being run, making ''opcache.file_cache'' or ''opcache.enable_cli=0'' a better choice). |
| |
==== Interactions with other opcache features ==== | ==== Interactions with other opcache features ==== |
| |
''opcache.no_cache'' takes precedence over ''opcache.file_cache'' and ''opcache.file_cache_only''. Neither the shared memory cache nor the file cache will be used when ''opcache.no_cache'' is enabled. | ''opcache.allow_cache=0'' takes precedence over ''opcache.file_cache'' and ''opcache.file_cache_only''. Neither the shared memory cache nor the file cache will be used when ''opcache.allow_cache=0'' is used to disable opcode caching. |
| |
It is an error to enable both ''opcache.no_cache'' and ''opcache.preload''. ''auto_prepend_file'' can be used instead of ''opcache.preload'' if you want to run a script before your file without caching it. | It is an error to both set ''opcache.allow_cache=0'' and provide a script to preload (''opcache.preload''). ''auto_prepend_file'' can be used instead of ''opcache.preload'' if you want to run a script before your file without caching it. |
| |
Opcache's opcode optimizations and JIT are unaffected. | Opcache's opcode optimizations and JIT are unaffected. |
The APIs those SAPIs use will be unaffected. | The APIs those SAPIs use will be unaffected. |
| |
Applications using the CLI, Development web server, embedded PHP, and so on will be able to take advantage of ''opcache.no_cache'' if it was useful to optimize without caching. | Applications using the CLI, Development web server, embedded PHP, and so on will be able to take advantage of ''opcache.allow_cache=0'' if it was useful to optimize without caching. |
| |
==== To Existing Extensions ==== | ==== To Existing Extensions ==== |
The code changes to opcache's optimization and caching are minimal - the implementation of this RFC is effectively the same ''opcache.file_cache_only'' without reading or writing files. | The code changes to opcache's optimization and caching are minimal - the implementation of this RFC is effectively the same ''opcache.file_cache_only'' without reading or writing files. |
| |
''opcache_get_status()'' now includes a new boolean ''optimization_enabled'', which is true if any optimization passes will get run. When ''no_cache'' is enabled, the array will include the field ''"no_cache" => true''. | ''opcache_get_status()'' now includes the following new booleans |
| |
| * ''optimizations_enabled'', which is true if any optimization passes will get run. |
| * ''allow_cache'', which will be true if opcache caching (in shared memory or the file cache) is enabled. |
| |
| ''opcache_get_status()'' already had the undocumented field ''opcache_enabled''. Looking at the implementation, it appears to be true when shared memory caching is successfully enabled, whether or not optimizations are enabled. Similarly to the existing behavior for ''file_cache_only'', when ''opcache.allow_cache=0'', the field ''opcache_enabled'' will be false. |
| |
==== php.ini Defaults ==== | ==== php.ini Defaults ==== |
| |
''opcache.no_cache=0'' (caching is allowed) will be the hardcoded default and the default value in php.ini-development and php.ini-production. | ''opcache.allow_cache=1'' (caching is allowed) will be the hardcoded default and the default value in ''php.ini-development'' and ''php.ini-production''. |
| |
===== Discussion ===== | ===== Discussion ===== |
</blockquote> | </blockquote> |
| |
On the PR implementing ''opcache.no_cache'', [[https://github.com/php/php-src/pull/5504#issuecomment-622295467|Nikita Popov wrote]]: | On the PR implementing ''opcache.allow_cache=0'', [[https://github.com/php/php-src/pull/5504#issuecomment-622295467|Nikita Popov wrote]]: |
| |
<blockquote> | <blockquote> |
</blockquote> | </blockquote> |
| |
* I would prefer to have this than have no way to disable caching. When an RFC/implementation for moving opcode caching into core is created, the authors could re-evaluate whether ''opcache.no_cache'' should continue to be used, and either continue using that setting name, or deprecate it and emit a migration notice/warning on startup. | * I would prefer to have this than have no way to disable caching. When an RFC/implementation for moving opcode caching into core is created, the authors could re-evaluate whether ''opcache.allow_cache=0'' should continue to be used, and either continue using that setting name, or deprecate it and emit a migration notice/warning on startup. |
* I think that creating a new setting along the lines of ''opcache.no_cache'' would have a use case before and after such a refactoring, providing the benefits I mentioned for the use cases in this RFC. This would continue to be have a use case even if the caching parts of ''opcache.so'' moved into PHP's core (e.g. if that was done, and the caching module were loaded in php.ini as zend_extension=''opcache.so'', there'd still be a use case for a configuration setting to override that default to disable caching for running individual programs) \\ \\ Users may strongly prefer for ''opcache.enable'', ''opcache.enable_cli'', and ''opcache.optimization_level'' to continue controlling whether optimizations are performed (so setting the combination of ''opcache.enable=1'', ''opcache.enable_cli=1'', and a setting such as ''opcache.no_cache=1'' to optimize without caching would still make sense even after optimizations were moved into core.) | * I think that creating a new setting along the lines of ''opcache.allow_cache=0'' would have a use case before and after such a refactoring, providing the benefits I mentioned for the use cases in this RFC. This would continue to be have a use case even if the caching parts of ''opcache.so'' moved into PHP's core (e.g. if that was done, and the caching module were loaded in php.ini as zend_extension=''opcache.so'', there'd still be a use case for a configuration setting to override that default to disable caching for running individual programs) \\ \\ Users may strongly prefer for ''opcache.enable'', ''opcache.enable_cli'', and ''opcache.optimization_level'' to continue controlling whether optimizations are performed (so setting the combination of ''opcache.enable=1'', ''opcache.enable_cli=1'', and a setting such as ''opcache.allow_cache=0'' to optimize without caching would still make sense even after optimizations were moved into core.) |
* If nobody's currently planning to work on moving the optimizer into Zend (i.e. into PHP's core), then it may be several minor releases before it's possible to have optimization without caching. | * If nobody's currently planning to work on moving the optimizer into Zend (i.e. into PHP's core), then it may be several minor releases before it's possible to have optimization without caching. |
* There may be unforeseen objections to moving the optimizer into Zend from creators/users of profiling tools, debuggers, code coverage tools, alternative optimizers (if any exist), etc. Hopefully not, but that'd depend on the proposed implementation details. | * There may be unforeseen objections to moving the optimizer into Zend from creators/users of profiling tools, debuggers, code coverage tools, alternative optimizers (if any exist), etc. Hopefully not, but that'd depend on the proposed implementation details. |
===== Future Scope ===== | ===== Future Scope ===== |
| |
* Normally, opcache optimizes a file based only on that one file's contents (this makes it safe to read from cache even when loading a different combination of files). When ''opcache.no_cache=1'' is used, it may be possible to use all of the class, function, constant, etc. definitions parsed from previously parsed files (to eliminate dead code, inline function calls, etc). https://wiki.php.net/rfc/preload mentioned something similar in the Future Scope. | * Normally, opcache optimizes a file based only on that one file's contents (this makes it safe to read from cache even when loading a different combination of files). When ''opcache.allow_cache=0'' is used, it may be possible to use all of the class, function, constant, etc. definitions parsed from previously parsed files (to eliminate dead code, inline function calls, etc). https://wiki.php.net/rfc/preload mentioned something similar in the Future Scope. |
| |
| ===== Vote ===== |
| |
| Voting started on May 30th and ends on June 13th |
| |
| <doodle title="Add opcache.allow_cache ini setting to support opcode optimization without caching" auth="tandre" voteType="single" closed="true"> |
| * Yes |
| * No |
| </doodle> |
| |
| ==== If you voted no, why? ==== |
| |
| The [[https://wiki.php.net/rfc/opcache.no_cache#discussion|Discussion]] section mentioned alternative approaches to this RFC. This feedback is being gathered if it may be useful for other work on Opcache such as moving optimizations into PHP's core. |
| |
| - I would only vote for optimizations without caching if Opcache's opcode optimizations were moved into core first. |
| - I don't want any form of optimization without caching / I think ''opcache.file_cache'' should be used instead |
| - I think different ini options/values should be used to do this |
| - Other |
| |
| <doodle title="If you voted no on opcache.allow_cache, why?" auth="tandre" voteType="multi" closed="true"> |
| * 1 |
| * 2 |
| * 3 |
| * 4 |
| </doodle> |
| |
| Also, would you be interested in moving opcode optimizations and the JIT out of the zend_extension opcache into PHP's core? |
| |
| <doodle title="I would be interested in moving opcode optimizations into core" auth="tandre" voteType="single" closed="true"> |
| * Yes |
| * No |
| </doodle> |
| |
| ===== Changelog ===== |
| |
| 0.2: Previously, the ini setting override to disable caching was ''opcache.no_cache=1''. This was changed to ''opcache.allow_cache=0'' to avoid double negatives and to be consistent with naming of other ini settings such as ''allow_url_fopen'' and ''allow_url_include''. |
| |
===== Proposed Voting Choices ===== | 0.3: Fix documentation of changes to ''opcache_get_status()'' |
| |
Add the ''opcache.no_cache'' ini setting to support opcode optimization without caching. (Yes/No vote, requiring 2/3 majority) | 0.4: Improve documentation of ini settings, add another example use case. |
| |
===== References ===== | ===== References ===== |
| |
https://externals.io/message/109959 opcache.no_cache prototype: Opcode optimization without caching | https://externals.io/message/109959 "opcache.no_cache prototype: Opcode optimization without caching" |
| |
| https://externals.io/message/110187 "[RFC] opcache.no_cache: Opcache optimization without any caching" |