rfc:opcache.no_cache

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Next revision
Previous revision
rfc:opcache.no_cache [2020/05/16 15:59]
tandre created
rfc:opcache.no_cache [2020/06/13 17:45] (current)
tandre add feedback comment on moving optimizations into core
Line 1: Line 1:
 ====== 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: Draft+  * 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
Line 11: Line 11:
 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. \\ (This 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)
   * Each shared memory block used for caching (and each additional file being cached) uses up RAM (Random-Access Memory) unnecessarily, when individual PHP processes are known to be long-lived and don't have a common memory address space. It's inefficient to cache opcodes in situations where the cache would never be used.   * Each shared memory block used for caching (and each additional file being cached) uses up RAM (Random-Access Memory) unnecessarily, when individual PHP processes are known to be long-lived and don't have a common memory address space. It's inefficient to cache opcodes in situations where the cache would never be used.
  
 ===== 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.
Line 56: Line 58:
 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 ====
Line 66: Line 68:
 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 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 implementationit 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 =====
Line 83: Line 90:
 </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>
Line 92: Line 99:
 </blockquote> </blockquote>
  
-  * 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 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.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.
Line 99: Line 107:
 ===== 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.
  
-===== Proposed Voting Choices =====+===== 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''
 + 
 +0.3: Fix documentation of changes to ''opcache_get_status()'' 
 + 
 +0.4: Improve documentation of ini settings, add another example use case. 
 + 
 +===== Ideas on moving the optimizer into core instead ===== 
 + 
 +There are various ways the suggestion in [[https://wiki.php.net/rfc/opcache.no_cache#discussion|Discussion]] could be implemented. My ideas on a way that could be implemented are below (I'm not familiar enough with opcache to implement that or to be aware of any problems it would cause): 
 + 
 +  * Move the optimizer into core (e.g. move code related to opcode optimizations from ''ext/opcache'' to a new folder <del>''ext/optimizer''</del> such as ''Zend/optimizer''). Keep all of the functionality related to caching in the zend_extension Zend Opcache (some build environments may not support or have a use case for any forms of shared memory caching). 
 +  * Continue optimizing according to ''opcache.enable'' and ''opcache.enable_cli'' when the opcode caching is enabled. \\ Add a new flag such as ''optimizer.always_optimize=1'' or ''opcache.always_optimize=1'' which will ignore that and unconditionally optimize using the optimization passes in ''opcache.optimization_level''. This would ensure that existing use cases work without modifying ''php.ini'' and won't suffer from high startup time for short-lived processes which don't have opcodes cached. 
 +  * Provide C function pointers to lock shared memory and acquire pointer locations so that the JIT can emit executable code without conflicting with other processes/threads, and make opcache override those function pointers. I'm not sure how protecting memory with opcache jit without the opcache extension managing shared memory would work with threaded php and no shared cache, but should be possible - I assume the JIT already works with ''opcache.file_cache_only''. I'm also unfamiliar with how those pointers/mutexes would get released if php crashed. 
 +  * Limit ''opcache.preload'' to only be used when the opcode caching zend_extension is used. 
 + 
 +[[https://externals.io/message/110502#110503|Nikita Popov mentions that]] 
 +<blockquote> 
 +To be clear, "move into core" means moving optimizations into Zend/ and making them part of the compilation process (optionally). They shouldn't be in a separate ext/optimizer extension -- that would be not much better than having them in ext/opcache :) 
 +</blockquote>
  
-Add the ''opcache.no_cache'' ini setting to support opcode optimization without caching. (Yes/No vote, requiring 2/3 majority) 
  
 ===== 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"
rfc/opcache.no_cache.1589644751.txt.gz · Last modified: 2020/05/16 15:59 by tandre