• 首页
  • vue
  • TypeScript
  • JavaScript
  • scss
  • css3
  • html5
  • php
  • MySQL
  • redis
  • jQuery
  • 位置: php 中文手册 -> php 绑定的扩展库

    opcache函数(PHP脚本缓存)

    Opcache是一种通过将解析的PHP脚本预编译的字节码(Operate Code)存放在共享内存中来避免每次加载和解析PHP脚本的开销,解析器可以直接从共享内存读取已经缓存的字节码(Operate Code),从而大大提高PHP的执行效率。

    当解释器完成对脚本代码的分析后,便将它们生成可以直接运行的中间代码,也称为操作码(Operate Code,opcode)。Opcode cache的目地是避免重复编译,减少CPU和内存开销。如果动态内容的性能瓶颈不在于CPU和内存,而在于I/O操作,比如数据库查询带来的磁盘I/O开销,那么opcode cache的性能提升是非常有限的。但是既然opcode cache能带来CPU和内存开销的降低,这总归是好事。现代操作码缓存器(Optimizer+,APC2.0+,其他)使用共享内存进行存储,并且可以直接从中执行文件,而不用在执行前“反序列化”代码。这将带来显着的性能加速,通常特别是高流量和高并发量时降低了整体服务器的内存消耗,而且很少有缺点。

    OPcache通过将 PHP 脚本预编译的字节码存储到共享内存中来提升 PHP 的性能, 存储预编译字节码的好处就是 省去了每次加载和解析 PHP 脚本的开销。PHP 5.5.0 及后续版本中已经绑定了 OPcache 扩展。 对于 PHP 5.2,5.3 和 5.4 版本可以使用 PECL 扩展中的 OPcache 库。

    这些函数的行为受php.ini中的设置影响。

    OPcache 配置选项
    名字默认可修改范围更新日志
    opcache.enable"1"PHP_INI_ALL
    opcache.enable_cli"0"PHP_INI_SYSTEM在 PHP 7.1.2 至 7.1.6 (含)的版本,默认值是"1"
    opcache.memory_consumption"128"PHP_INI_SYSTEM在 PHP 7.0.0 之前,默认值是 "64"
    opcache.interned_strings_buffer"8"PHP_INI_SYSTEM在 PHP 7.0.0 之前,默认值是 "4"
    opcache.max_accelerated_files"10000"PHP_INI_SYSTEM在 PHP 7.0.0 之前,默认值是 "2000"
    opcache.max_wasted_percentage"5"PHP_INI_SYSTEM
    opcache.use_cwd"1"PHP_INI_SYSTEM
    opcache.validate_timestamps"1"PHP_INI_ALL
    opcache.revalidate_freq"2"PHP_INI_ALL
    opcache.revalidate_path"0"PHP_INI_ALL
    opcache.save_comments"1"PHP_INI_SYSTEM
    opcache.load_comments"1"PHP_INI_ALL从 PHP 7.0.0 开始被移除
    opcache.fast_shutdown"0"PHP_INI_SYSTEM从 PHP 7.2.0 开始被移除
    opcache.enable_file_override"0"PHP_INI_SYSTEM
    opcache.optimization_level"0x7FFFBFFF"PHP_INI_SYSTEM从 PHP 5.6.18 开始,默认值从 0xFFFFFFFF 修改为 0x7FFFBFFF
    opcache.inherited_hack"1"PHP_INI_SYSTEM自 PHP 7.3.0 被移除
    opcache.dups_fix"0"PHP_INI_ALL
    opcache.blacklist_filename""PHP_INI_SYSTEM
    opcache.max_file_size"0"PHP_INI_SYSTEM
    opcache.consistency_checks"0"PHP_INI_ALL
    opcache.force_restart_timeout"180"PHP_INI_SYSTEM
    opcache.error_log""PHP_INI_SYSTEM
    opcache.log_verbosity_level"1"PHP_INI_SYSTEM
    opcache.preferred_memory_model""PHP_INI_SYSTEM
    opcache.protect_memory"0"PHP_INI_SYSTEM
    opcache.mmap_baseNULLPHP_INI_SYSTEM
    opcache.restrict_api""PHP_INI_SYSTEM
    opcache.file_update_protection"2"PHP_INI_ALL
    opcache.huge_code_pages"0"PHP_INI_SYSTEM
    opcache.lockfile_path"/tmp"PHP_INI_SYSTEM
    opcache.opt_debug_level"0"PHP_INI_SYSTEM
    opcache.file_cacheNULLPHP_INI_SYSTEM从 PHP 7.0.0 开始支持
    opcache.file_cache_only"0"PHP_INI_SYSTEM从 PHP 7.0.0 开始支持
    opcache.file_cache_consistency_checks"1"PHP_INI_SYSTEM从 PHP 7.0.0 开始支持
    opcache.file_cache_fallback"1"PHP_INI_SYSTEM从 PHP 7.0.0 开始支持,仅适用于 Windows 平台
    opcache.validate_permission"0"PHP_INI_SYSTEM从 PHP 7.0.14 开始支持
    opcache.validate_root"0"PHP_INI_SYSTEM从 PHP 7.0.14 开始支持
    opcache.preload""PHP_INI_SYSTEM从 PHP 7.4.0 开始支持
    opcache.preload_user""PHP_INI_SYSTEM从 PHP 7.4.0 开始支持
    有关 PHP_INI_* 样式的更多详情与定义,见 配置可被设定范围。

    这是配置指令的简短说明。

    opcache.enableboolean

    启用操作码缓存。如果禁用此选项,则不会优化和缓存代码。 在运行期使用 ini_set() 函数只能禁用opcache.enable设置,不可以启用此设置。 如果在脚本中尝试启用此设置项会产生警告。

    opcache.enable_cliboolean

    仅针对 CLI 版本的 PHP 启用操作码缓存。 通常被用来测试和调试。

    opcache.memory_consumptioninteger

    OPcache 的共享内存大小,以兆字节为单位。

    opcache.interned_strings_bufferinteger

    用来存储预留字符串的内存大小,以兆字节为单位。 PHP 5.3.0 之前的版本会忽略此配置指令。

    opcache.max_accelerated_filesinteger

    OPcache 哈希表中可存储的脚本文件数量上限。 真实的取值是在质数集合{ 223, 463, 983, 1979, 3907, 7963, 16229, 32531, 65407, 130987 }中找到的第一个大于等于设置值的质数。 设置值取值范围最小值是 200,最大值在 PHP 5.5.6 之前是 100000,PHP 5.5.6 及之后是 1000000。

    opcache.max_wasted_percentageinteger

    浪费内存的上限,以百分比计。 如果达到此上限,那么 OPcache 将产生重新启动续发事件。

    opcache.use_cwdboolean

    如果启用,OPcache 将在哈希表的脚本键之后附加改脚本的工作目录, 以避免同名脚本冲突的问题。 禁用此选项可以提高性能,但是可能会导致应用崩溃。

    opcache.validate_timestampsboolean

    如果启用,那么 OPcache 会每隔 opcache.revalidate_freq 设定的秒数 检查脚本是否更新。 如果禁用此选项,你必须使用 opcache_reset() 或者 opcache_invalidate() 函数来手动重置 OPcache,也可以 通过重启 Web 服务器来使文件系统更改生效。

    opcache.revalidate_freqinteger

    检查脚本时间戳是否有更新的周期,以秒为单位。 设置为0会导致针对每个请求, OPcache 都会检查脚本更新。

    如果 opcache.validate_timestamps 配置指令设置为禁用,那么此设置项将会被忽略。

    opcache.revalidate_pathboolean

    如果禁用此选项,在同一个 include_path 已存在的缓存文件会被重用。 因此,将无法找到不在包含路径下的同名文件。

    opcache.save_commentsboolean

    如果禁用,脚本文件中的注释内容将不会被包含到操作码缓存文件, 这样可以有效减小优化后的文件体积。 禁用此配置指令可能会导致一些依赖注释或注解的 应用或框架无法正常工作, 比如: Doctrine, Zend Framework 2 以及 PHPUnit。

    opcache.load_commentsboolean

    如果禁用,则即使文件中包含注释,也不会加载这些注释内容。 本选项可以和 opcache.save_comments 一起使用,以实现按需加载注释内容。

    opcache.fast_shutdownboolean

    如果启用,则会使用快速停止续发事件。 所谓快速停止续发事件是指依赖 Zend 引擎的内存管理模块 一次释放全部请求变量的内存,而不是依次释放每一个已分配的内存块。

    从 PHP 7.2.0 开始,此配置指令被移除。 快速停止的续发事件的处理已经集成到 PHP 中, 只要有可能,PHP 会自动处理这些续发事件。

    opcache.enable_file_overrideboolean

    如果启用,则在调用函数 file_exists(), is_file() 以及 is_readable() 的时候, 都会检查操作码缓存,无论文件是否已经被缓存。 如果应用中包含检查 PHP 脚本存在性和可读性的功能,这样可以提升性能。 但是如果禁用了 opcache.validate_timestamps 选项, 可能存在返回过时数据的风险。

    opcache.optimization_levelinteger

    控制优化级别的二进制位掩码。

    opcache.inherited_hackboolean

    在 PHP 5.3 之前的版本,OPcache 会存储代码中使用 DECLARE_CLASS 操作码 来实现继承的位置。当文件被加载之后,OPcache 会尝试使用当前环境来绑定被继承的类。 由于当前脚本中可能并不需要 DECLARE_CLASS 操作码,如果这样的脚本需要对应的操作码被定义时, 可能无法运行。

    在 PHP 5.3 及后续版本中,此配置指令会被忽略。

    opcache.dups_fixboolean

    仅作为针对 “不可重定义类”错误的一种解决方案。

    opcache.blacklist_filenamestring

    OPcache 黑名单文件位置。 黑名单文件为文本文件,包含了不进行预编译优化的文件名,每行一个文件名。 黑名单中的文件名可以使用通配符,也可以使用前缀。 此文件中以分号(;)开头的行将被视为注释。

    简单的黑名单文件可能如下所示:

    ; 将特定文件加入到黑名单
    /var/www/broken.php
    ; 以字符 x 文件打头的文件
    /var/www/x
    ; 通配符匹配
    /var/www/*-broken.php
    
    opcache.max_file_sizeinteger

    以字节为单位的缓存的文件大小上限。设置为0表示缓存全部文件。

    opcache.consistency_checksinteger

    如果是非 0 值,OPcache 将会每隔 N 次请求检查缓存校验和。 N 即为此配置指令的设置值。 由于此选项对于性能有较大影响,请尽在调试环境使用。

    opcache.force_restart_timeoutinteger

    如果缓存处于非激活状态,等待多少秒之后计划重启。 如果超出了设定时间,则 OPcache 模块将杀除持有缓存锁的进程, 并进行重启。

    如果选项 opcache.log_verbosity_level 设置为 2 或者 2 以上的数值,当发生重启时将在日志中记录一条警告信息。

    opcache.error_logstring

    OPcache 模块的错误日志文件。 如果留空,则视为stderr, 错误日志将被送往标准错误输出 (通常情况下是 Web 服务器的错误日志文件)。

    opcache.log_verbosity_levelinteger

    OPcache 模块的日志级别。 默认情况下,仅有致命级别(0)及错误级别(1)的日志会被记录。 其他可用的级别有:警告(2),信息(3)和调试(4)。

    opcache.preferred_memory_modelstring

    OPcache 首选的内存模块。 如果留空,OPcache 会选择适用的模块, 通常情况下,自动选择就可以满足需求。

    可选值包括:mmapshm,posix以及win32

    opcache.protect_memoryboolean

    保护共享内存,以避免执行脚本时发生非预期的写入。 仅用于内部调试。

    opcache.mmap_basestring

    在 Windows 平台上共享内存段的基地址。 所有的 PHP 进程都将共享内存映射到同样的地址空间。 使用此配置指令避免“无法重新附加到基地址”的错误。

    opcache.restrict_apistring

    仅允许路径是以指定字符串开始的 PHP 脚本调用 OPcache API 函数。 默认值为空字符串 "",表示不做限制。

    opcache.file_update_protectionstring

    如果文件的最后修改时间距现在不足此项配置指令所设定的秒数,那么这个文件不会进入到缓存中。 这是为了防止尚未完全修改完毕的文件进入到缓存。 如果你的应用中不存在部分修改文件的情况,把此项设置为 0 可以提高性能。

    opcache.huge_code_pagesstring

    启用或者禁用将 PHP 代码(文本段)拷贝到 HUGE PAGES 中。 此项配置指令可以提高性能,但是需要在 OS 层面进行对应的配置。

    opcache.lockfile_pathstring

    用来存储共享锁文件的绝对路径(仅适用于 *nix 操作系统)。

    opcache.opt_debug_levelstring

    出于对不同阶段的优化情况进行调试的目的,生成操作码转储。 设置为 0x10000 会在进行优化之前输出编译器编译后的操作码, 设置为 0x20000 会输出优化后的操作码。

    opcache.file_cachestring

    配置二级缓存目录并启用二级缓存。 启用二级缓存可以在 SHM 内存满了、服务器重启或者重置 SHM 的时候提高性能。 默认值为空字符串 "",表示禁用基于文件的缓存。

    opcache.file_cache_onlyboolean

    启用或禁用在共享内存中的 opcode 缓存。

    opcache.file_cache_consistency_checksboolean

    当从文件缓存中加载脚本的时候,是否对文件的校验和进行验证。

    opcache.file_cache_fallbackboolean

    在 Windows 平台上,当一个进程无法附加到共享内存的时候, 使用基于文件的缓存,也即:opcache.file_cache_only=1。 需要显示的启用文件缓存。

    Caution

    不鼓励禁用此配置项, 禁用它可能会导致进程无法启动。

    opcache.validate_permissionboolean

    针对当前用户,验证缓存文件的访问权限。

    opcache.validate_rootboolean

    在 chroot 的环境中避免命名冲突。 为了防止进程访问到 chroot 环境之外的文件,应该在 chroot 的情况下启用这个选项。

    opcache.preloadstring

    指定要在服务器启动时期进行编译和缓存的 PHP 脚本文件, 这些文件也可能通过 include 或者 opcache_compile_file() 函数 来预加载其他文件。 所有这些文件中包含的实体,包括函数、类等,在服务器启动的时候就被加载和缓存, 对于用户代码来讲是“开箱可用”的。

    opcache.preload_userstring

    考虑到安全因素,禁止以 root 用户预加载代码。该指令方便以其他用户预加载。

    When using PHP on a windows platform and enabling opcache, you might run into occasional 500 errors. These will appear to show up entirely random.
    When this happens, your windows Event log (Windows Logs/Application) will show (probably multiple) entries from Zend OPcache with Event ID 487. Further information will state the following error message: "Base address marks unusable memory region".
    This issue can be resolved by adding the following to your php.ini:
      opcache.mmap_base = 0x20000000
    Unfortunately I do not know the significance of the value "0x20000000". I can only tell you that this value works to solve the problem (Tried and tested)
    The optimization levels as of php 7.3 are the following:
    #define ZEND_OPTIMIZER_PASS_1    (1<<0)  /* CSE, STRING construction   */
    #define ZEND_OPTIMIZER_PASS_2    (1<<1)  /* Constant conversion and jumps */
    #define ZEND_OPTIMIZER_PASS_3    (1<<2)  /* ++, +=, series of jumps   */
    #define ZEND_OPTIMIZER_PASS_4    (1<<3)  /* INIT_FCALL_BY_NAME -> DO_FCALL */
    #define ZEND_OPTIMIZER_PASS_5    (1<<4)  /* CFG based optimization    */
    #define ZEND_OPTIMIZER_PASS_6    (1<<5)  /* DFA based optimization    */
    #define ZEND_OPTIMIZER_PASS_7    (1<<6)  /* CALL GRAPH optimization   */
    #define ZEND_OPTIMIZER_PASS_8    (1<<7)  /* SCCP (constant propagation) */
    #define ZEND_OPTIMIZER_PASS_9    (1<<8)  /* TMP VAR usage        */
    #define ZEND_OPTIMIZER_PASS_10    (1<<9)  /* NOP removal         */
    #define ZEND_OPTIMIZER_PASS_11    (1<<10) /* Merge equal constants    */
    #define ZEND_OPTIMIZER_PASS_12    (1<<11) /* Adjust used stack      */
    #define ZEND_OPTIMIZER_PASS_13    (1<<12) /* Remove unused variables   */
    #define ZEND_OPTIMIZER_PASS_14    (1<<13) /* DCE (dead code elimination) */
    #define ZEND_OPTIMIZER_PASS_15    (1<<14) /* (unsafe) Collect constants */
    #define ZEND_OPTIMIZER_PASS_16    (1<<15) /* Inline functions */
    Source: https://lxr.room11.org/xref/php-src%40master/ext/opcache/Optimizer/zend_optimizer.h
    It should be noted that according to the original RFC (https://wiki.php.net/rfc/preload) `opcache.preload` caches preloaded files *forever* for all instances of the underlying PHP process.
    That means, that hosting multiple websites on the same server might result in some unexpected behaviour.
    Concrete example: 
    - you have a Symfony 3.2 App (which might be an endpoint of some type) and a Symfony 3.4 App (which might be your main application)
    - both apps have a main Class called App that is in the same namespace (as it is usual, since the class name is unique to each project)
    - depending on which app is loaded first, one or the other will work, since `opcache.preload` has no file based distinction of what class is used where and simply provides them to the user space
    This is avoidable by simply not preloading user space classes or, if you work with FPM, by defining a pool for each app.
    In order to optimize memory consumption, you might also use a common FPM Pool for all Symfony 3.4 Apps and preload the entire framework in there and simply not preload user space classes (which might be cached by opcache anyway but is slower, since it will be checked if the file has changed on every request).
    It would appear as though the [opcache.enable] setting is indeed NOT PHP_INI_ALL.
    For changing it within user.ini yields no effect when disabled at global level. user.ini is ignored for that setting.
    Is opcache.memory_consumption limited by max_memory? If not what limitations are there, can you have too much?
    opcache.max_wasted_percentage must have a value between 1 and 50. Otherwise it will automatically set the variable 5 %.