转载  https://www.zybuluo.com/phper/note/1016714

啥是Opcode?

我们在日常的PHP开发过程中,应该经常会听见Opcache这个词,那么啥是Opcode呢?

Opcache 的前生是 Optimizer+ ,它是PHP的官方公司 Zend 开发的一款闭源但可以免费使用的 PHP 优化加速组件。 Optimizer+ 将PHP代码预编译生成的脚本文件 Opcode 缓存在共享内存中供以后反复使用,从而避免了从磁盘读取代码再次编译的时间消耗。同时,它还应用了一些代码优化模式,使得代码执行更快。从而加速PHP的执行。

Optimizer+ 于 2013年3月中旬改名为 Opcache。并且在 PHP License 下开源: https://github.com/zendtech/ZendOptimizerPlus

Opcache的生命周期

了解了啥是Opcache以及Opcache的作用。现在看一下Opcache的运行图。

正常的php代码的执行过程如下:

request请求(nginx,apache,cli等)-->Zend引擎读取.php文件-->扫描其词典和表达式 -->解析文件-->创建要执行的计算机代码(称为Opcode)-->最后执行Opcode--> response 返回

每一次请求PHP脚本都会执行一遍以上步骤,如果PHP源代码没有变化,那么Opcode也不会变化,显然没有必要每次都重行生成Opcode,结合在Web中无所不在的缓存机制,我们可以把Opcode缓存下来,以后直接访问缓存的Opcode岂不是更快,启用Opcode缓存之后的流程图如下所示:

request请求(nginx,apache,cli等)-->Zend引擎读取.php文件-->读取Opcode-->执行Opcode--> response 返回

Opcache的安装

实际上,在php5.5以后,Opcache 是默认安装好了的,已经不需要我们再手动去安装了,但是默认是没有开启的,如果我们需要使用,需要手动去开启:

  1. zend_extension=opcache.so
  2. [opcache]
  3. opcache.enable=1 #允许在web环境使用,默认是开启的。
  4. opcache.enable_cli=1 #运行在cli环境使用

重启 fpm 和 nginx

  1. kill -USR2 cat `/usr/local/php/var/run/php-fpm.pid`
  2. nginx -s reload

这样就可以使用opcache了。

推荐的 php.ini 中 Opcache的配置

以下是官网推荐的php.ini中的配置。可以在生产环境获得更高的性能:

  1. opcache.enable=1
  2. opcache.memory_consumption=128
  3. opcache.interned_strings_buffer=8
  4. opcache.max_accelerated_files=4000
  5. opcache.revalidate_freq=60
  6. opcache.fast_shutdown=1 ;(在PHP 7.2.0中被移除,会自动开启)
  7. opcache.enable_cli=1

opcache的配置说明。

上面是官方推荐的一些配置,其实它还有一大长条的配置,我们选择几个重要的,会被使用到的,来说下他们的具体含义:

  1. opcache.enable=1 (default "1")
  2. ;OPcache打开/关闭开关。当设置为Off或者0时,会关闭Opcache, 代码没有被优化和缓存。
  3. opcache.enable_cli=1 (default "0")
  4. ;CLI环境下,PHP启用OPcache。这主要是为了测试和调试。从 PHP 7.1.2 开始,默认启用。
  5. opcache.memory_consumption=128 (default "64")
  6. ;OPcache共享内存存储大小。用于存储预编译的opcode(以MB为单位)。
  7. opcache.interned_strings_buffer=8 (default "4")
  8. ;这是一个很有用的选项,但是似乎完全没有文档说明。PHP使用了一种叫做字符串驻留(string interning)的技术来改善性能。例如,如果你在代码中使用了1000次字符串“foobar”,在PHP内部只会在第一使用这个字符串的时候分配一个不可变的内存区域来存储这个字符串,其他的999次使用都会直接指向这个内存区域。这个选项则会把这个特性提升一个层次——默认情况下这个不可变的内存区域只会存在于单个php-fpm的进程中,如果设置了这个选项,那么它将会在所有的php-fpm进程中共享。在比较大的应用中,这可以非常有效地节约内存,提高应用的性能。
  9. 这个选项的值是以兆字节(megabytes)作为单位,如果把它设置为16,则表示16MB,默认是4MB,这是一个比较低的值。
  10. opcache.max_accelerated_files (default "2000")
  11. ;这个选项用于控制内存中最多可以缓存多少个PHP文件。这个选项必须得设置得足够大,大于你的项目中的所有PHP文件的总和。
  12. 设置值取值范围最小值是 200,最大值在 PHP 5.5.6 之前是 100000,PHP 5.5.6 及之后是 1000000。也就是说在200到1000000之间。
  13. 你可以运行“find . -type f -print | grep php | wc -l”这个命令来快速计算你的代码库中的PHP文件数。
  14. opcache.max_wasted_percentage (default "5")
  15. ;计划重新启动之前,“浪费”内存的最大百分比。
  16. opcache.use_cwd (default "1")
  17. ;如果启用,OPcache将在哈希表的脚本键之后附加改脚本的工作目录, 以避免同名脚本冲突的问题。禁用此选项可以提高性能,但是可能会导致应用崩溃
  18. opcache.validate_timestamps (default "1")
  19. ;如果启用(设置为1),OPcache会在opcache.revalidate_freq设置的秒数去检测文件的时间戳(timestamp)检查脚本是否更新。
  20. 如果这个选项被禁用(设置为0),opcache.revalidate_freq会被忽略,PHP文件永远不会被检查。这意味着如果你修改了你的代码,然后你把它更新到服务器上,再在浏览器上请求更新的代码对应的功能,你会看不到更新的效果,你必须使用 `opcache_reset()` 或者 `opcache_invalidate()` 函数来手动重置 OPcache。或者重重你的web服务器或者php-fpm 来使文件系统更改生效。
  21. 我强烈建议你在生产环境中设置为0,why?因为当你在更新服务器代码的时候,如果代码较多,更新操作是有些延迟的,在这个延迟的过程中必然出现老代码和新代码混合的情况,这个时候对用户请求的处理必然存在不确定性。最后,等所有的代码更新完毕后,再平滑重启PHP和web服务器。
  22. opcache.revalidate_freq (default "2")
  23. ;这个选项用于设置缓存的过期时间(单位是秒),当这个时间达到后,opcache会检查你的代码是否改变,如果改变了PHP会重新编译它,生成新的opcode,并且更新缓存。值为“0”表示每次请求都会检查你的PHP代码是否更新(这意味着会增加很多次stat系统调用,译注:stat系统调用是读取文件的状态,这里主要是获取最近修改时间,这个系统调用会发生磁盘I/O,所以必然会消耗一些CPU时间,当然系统调用本身也会消耗一些CPU时间)。可以在开发环境中把它设置为0,生产环境下不用管。
  24. 如果 `opcache.validate_timestamps` 配置指令设置为禁用(设置为0),那么此设置项将会被忽略。
  25. opcache.revalidate_path (default "0")
  26. ;在include_path优化中启用或禁用文件搜索
  27. 如果被禁用,并且找到了使用的缓存文件相同的include_path,该文件不被再次搜索。因此,如果一个文件与include_path中的其他地方相同的名称出现将不会被发现。如果此优化对此有效,请启用此指令你的应用程序,这个指令的默认值是禁用的,这意味着该优化是活跃的。
  28. opcache.fast_shutdown(默认“0”)
  29. ;如果启用,则会使用快速停止续发事件。 所谓快速停止续发事件是指依赖 Zend 引擎的内存管理模块 一次释放全部请求变量的内存,而不是依次释放每一个已分配的内存块。
  30. 该指令已在PHP 7.2.0中被删除。快速关机序列的一个变种已经被集成到PHP中,并且如果可能的话将被自动使用。

验证opcache是否生效

当我们开启Opcache后,然后也配置好了相关的配置,那么如何验证是否已经成功了呢?

写了简单的小例子,先把检查时间设置为10秒,也就是说10秒内,不会去检查文件是否有更新,直接用缓存中的opcode:

  1. zend_extension=opcache.so
  2. [opcache]
  3. opcache.enable=1
  4. opcache.memory_consumption=128
  5. opcache.interned_strings_buffer=8
  6. opcache.max_accelerated_files=4000
  7. opcache.revalidate_freq=10
  8. opcache.fast_shutdown=1
  9. opcache.enable_cli=1

然后一个简单的例子:

  1. //php71.php
  2. <?php
  3. $a = '12';
  4. echo $a;

启动一个php自带的web服务:

  1. php -S 127.0.0.1:8088

然后再浏览器里打开:

  1. http://127.0.0.1:8088/php71.php

结果是:12

然后,手动改下:

  1. //php71.php
  2. <?php
  3. $a = '34';
  4. echo $a;

如果你手速快,迅速的去刷新浏览器,10次内,你会发现,结果还是12。不是 34。

说明,Opcache 已经生效了。

再来改一下,把opcache.validate_timestamps=0设置为0,则表示,永远不去检查文件是否更新。

然后,你刷新页面,数字永远是12。除非你ctrl+c 关闭web服务,再启动web服务,才会生效变成 34。

所以,在一般的公司代码上线发布后,都会平滑重启php或者web服务器

opcache相关的几个函数

虽然opcahce是php内置的行为,只要你开启了,就会生效,不需要像传统的redis或者memcache需要手动写代码才能使用。但是php也提供了若干个opcache相关的函数。

  • opcache_compile_file — 无需运行,即可编译并缓存 PHP 脚本
  • opcache_get_configuration — 获取php.ini中的配置信息
  • opcache_get_status — 获取缓存的状态信息
  • opcache_invalidate — 废除脚本缓存
  • opcache_is_script_cached — 一个php文件是否被缓存
  • opcache_reset — 重置情况所有的缓存内容

我们来一一看下。

opcache_compile_file

使用此函数,可以无需运行php脚本,即可编译并缓存 PHP 脚本。该函数可用于在 Web 服务器重启之后初始化缓存,俗称缓存预热。

注意:文件必须填写完整全路径

我们还是举例子说明:

php71.php

  1. $a = '5678';
  2. echo $a;
  3. //是否被缓存
  4. var_dump(opcache_invalidate('/Users/tencent/php/php71.php'));
  5. //查看缓存状态
  6. var_dump(opcache_get_status());

每次重启web服务器,第一次刷新浏览器这个页面,查看打印:

  1. 5678
  2. bool(false)
  3. .....
  4. ["hits"]=> int(0)
  5. .....

可以,看出,第一次进来,是没有被缓存的,第二次刷新,就被缓存住了。

  1. 5678
  2. bool(true)
  3. .....
  4. ["hits"]=> int(1)
  5. .....

opcache_get_configuration

查看php.ini中的配置项,和php.ini里的设置一样,并列出所有的配置,以数组array的形式呈现,用 json_encode 打印出来:

  1. {
  2. "directives": {
  3. "opcache.enable": true,
  4. "opcache.enable_cli": true,
  5. "opcache.use_cwd": true,
  6. "opcache.validate_timestamps": true,
  7. "opcache.validate_permission": false,
  8. "opcache.validate_root": false,
  9. "opcache.inherited_hack": true,
  10. "opcache.dups_fix": false,
  11. "opcache.revalidate_path": false,
  12. "opcache.log_verbosity_level": 1,
  13. "opcache.memory_consumption": 134217728,
  14. "opcache.interned_strings_buffer": 8,
  15. "opcache.max_accelerated_files": 4000,
  16. "opcache.max_wasted_percentage": 0.05,
  17. "opcache.consistency_checks": 0,
  18. "opcache.force_restart_timeout": 180,
  19. "opcache.revalidate_freq": 10,
  20. "opcache.preferred_memory_model": "",
  21. "opcache.blacklist_filename": "",
  22. "opcache.max_file_size": 0,
  23. "opcache.error_log": "",
  24. "opcache.protect_memory": false,
  25. "opcache.save_comments": true,
  26. "opcache.enable_file_override": false,
  27. "opcache.optimization_level": 2147467263,
  28. "opcache.lockfile_path": "/tmp",
  29. "opcache.file_cache": "",
  30. "opcache.file_cache_only": false,
  31. "opcache.file_cache_consistency_checks": true
  32. },
  33. "version": {
  34. "version": "7.2.0",
  35. "opcache_product_name": "Zend OPcache"
  36. },
  37. "blacklist": []
  38. }

opcache_get_status

获取opcache的缓存状态以及缓存了哪些文件等信息,可以说是用的做多的一个脚本了。

打印出来:

  1. {
  2. "opcache_enabled": true,
  3. "cache_full": false,
  4. "restart_pending": false,
  5. "restart_in_progress": false,
  6. "memory_usage": {
  7. "used_memory": 18278720,
  8. "free_memory": 115919680,
  9. "wasted_memory": 19328,
  10. "current_wasted_percentage": 0.014400482177734375
  11. },
  12. "interned_strings_usage": {
  13. "buffer_size": 8388608,
  14. "used_memory": 428056,
  15. "free_memory": 7960552,
  16. "number_of_strings": 9963
  17. },
  18. "opcache_statistics": {
  19. "num_cached_scripts": 1,
  20. "num_cached_keys": 1,
  21. "max_cached_keys": 7963,
  22. "hits": 2,
  23. "start_time": 1516850948,
  24. "last_restart_time": 0,
  25. "oom_restarts": 0,
  26. "hash_restarts": 0,
  27. "manual_restarts": 0,
  28. "misses": 4,
  29. "blacklist_misses": 0,
  30. "blacklist_miss_ratio": 0,
  31. "opcache_hit_rate": 33.33333333333333
  32. },
  33. "scripts": {
  34. "/Users/tencent/php/php71.php": {
  35. "full_path": "/Users/tencent/php/php71.php",
  36. "hits": 0,
  37. "memory_consumption": 6432,
  38. "last_used": "Thu Jan 25 11:32:03 2018",
  39. "last_used_timestamp": 1516851123,
  40. "timestamp": 1516851119
  41. }
  42. }
  43. }

opcache_invalidate

废除(删除)一个文件的缓存。可以针对一个文件的清楚缓存。注意:文件必须填写完整全路径

  1. //清楚 php71.php缓存
  2. var_dump(opcache_invalidate('/Users/tencent/php/php71.php')); // bool(true)

opcache_is_script_cached

查看一个文件是否被缓存。注意:文件必须填写完整全路径

  1. var_dump(opcache_is_script_cached('/Users/tencent/ams-swoole-framework/php71.php'));
  2. //bool(true)
  3. var_dump(opcache_is_script_cached('/Users/tencent/ams-swoole-framework/php73.php'));
  4. // bool(false)

opcache_reset

重置所有的opcache缓存。注意:这个函数很危险,他会清空当前项目的所有opcache缓存:

  1. var_dump(opcache_reset()); //bool(true)

opcache图形化管理工具

上面的函数命令用起来可能没那么方便,基于上面的这些函数,有2个GUI的图形化管理工具,还不错。

1. 拥有漂亮的图形化界面的项目

    https://github.com/PeeHaa/OpCacheGUI

下载后,将config.sample.php 复制一份成为:config.php。并修改账户密码和时区:

  1. return [
  2. 'username' => 'root',
  3. 'password' => '$2y$10$XIlZ702pFKgRozYUuvaI4uZcumv19bysFo6PnviZIKlN8IvEeXVXu', //root
  4. 'whitelist' => [
  5. 'localhost',
  6. '127.0.0.1',
  7. ],
  8. 'language' => 'en',
  9. 'timezone' => 'Asia/Shanghai',
  10. 'error_reporting' => E_ALL,
  11. 'display_errors' => 'Off',
  12. 'log_errors' => 'On',
  13. 'uri_scheme' => Router::URL_REWRITE
  14. ];

然后在浏览器访问,输入账户密码:root root:

http://127.0.0.1:8089/index.php

2. 单个PHP文件, 方便部署的项目

    https://github.com/rlerdorf/opcache-status

下载后,然后在浏览器访问:

    http://127.0.0.1:8089/opcache.php

opcache性能测试

那么,开启opcache性能是否有很大的性能提升呢?

Opcode是啥以及如何使用好Opcache的更多相关文章

  1. [转]Opcode是啥以及如何使用好Opcache

    转载链接:Opcode是啥以及如何使用好Opcache 啥是Opcode? 我们在日常的PHP开发过程中,应该经常会听见Opcache这个词,那么啥是Opcode呢? Opcache 的前生是 Opt ...

  2. PHP7开启Opcode开启强悍性能

    鸟哥在博客中说,提高PHP 7性能的几个tips,第一条就是开启opcache: 记得启用Zend Opcache, 因为PHP7即使不启用Opcache速度也比PHP-5.6启用了Opcache快, ...

  3. 什么是 Opcache,如何使用 Opcache

    Opcode 是啥? 我们先看一下 PHP 的执行过程: PHP 初始化执行环节,启动 Zend 引擎,加载注册的扩展模块. 初始化后读取 PHP 脚本文件,Zend 引擎对 PHP 文件进行词法分析 ...

  4. [转载]PHP 5.6 on CentOS/RHEL 7.0 and 6.6 via Yum

    https://webtatic.com/packages/php56/ PHP 5.6.5 has been released on PHP.net on 22nd January 2014, an ...

  5. opcache,opcode,apc和apcu的区别

    opcode opcode是php解析器生成的操作码,类似java的字节码,main.class文件. opcache opcache是php的扩展,是一个实现将PHP字节码(OPCode)缓存到共享 ...

  6. 编译安装 Zend Opcache 缓存Opcache,加速 PHP

    Optimizer+ 是 Zend 开发的闭源但可以免费使用的 PHP 优化加速组件,是第一个也是最快的 opcode 缓存工具.现在,Zend 科技公司将 Optimizer+ 在 PHP Lice ...

  7. PHP 缓存扩展opcache

    opcache (全程 zend opcache): 从php5.5开始,默认提供的php脚本缓存扩展,编译php5.5时加上参数--enable-opcache就可以编译opcache了,只是要启用 ...

  8. 深入了解php opcode缓存原理

    什么是opcode opcode(operate code)是计算机指令中的一部分,用于指定要执行的操作,指令的格式和规范由处理器的指定规范指定 opcode是一种php脚本编译后的中间语言,就像ja ...

  9. 黄聪:深入理解PHP Opcode缓存原理

    什么是opcode缓存? 当解释器完成对脚本代码的分析后,便将它们生成可以直接运行的中间代码,也称为操作码(Operate Code,opcode).Opcode cache的目地是避免重复编译,减少 ...

随机推荐

  1. CHARACTER SET

    mysql> show tables; +-----------------+ | Tables_in_w0811 | +-----------------+ | t | | w_engine ...

  2. Struts2中.properties文件放置路径(classpath)

    一.web应用的classpath简介   classpath路径,即WEB-INF下面的classes目录,所有src目录下面的java.xml.properties等文件编译后都会在此. Stru ...

  3. tomcat端口设置

    在tomcat安装目录下,编辑/conf/server.properties 更改对应的端口: 然后系统重启就可以了.

  4. vue监听路由的变化,跳转到同一个页面时,Url改变但视图未重新加载问题

    引入:https://q.cnblogs.com/q/88214/ 解决方法: 添加路由监听,路由改变时执行监听方法 methods:{ fetchData(){ console.log('路由发送变 ...

  5. 关于eclipse调试时程序控制台不能自动打开

      对于这个程序,在刚开始的时候,没有敲上22,29,33行的打印语句时,在调试的时候不会自动弹开控制台,所以一直在怀疑代码可能出错了.因此可以自己手动打开,但是如果敲上那些代码,系统可以自动弹开控制 ...

  6. 20190122 Oracle if-- elsif -- else -- if end

    DECLARE V_SYSTIME VARCHAR2(8); PROCEDURE KB_RUNNING(I_DATE DATE) IS BEGIN V_SYSTIME :=TO_CHAR(I_DATE ...

  7. abap中结构体嵌套结构体。

    1: 结构体中嵌套结构体. *&---------------------------------------------------------------------* *& Re ...

  8. MYSQL: set names utf8是什么意思?

    set names utf8 是用于设置编码,可以再在建数据库的时候设置,也可以在创建表的时候设置,或只是对部分字段进行设置,而且在设置编码的时候,这些地方最好是一致的,这样能最大程度上避免数据记录出 ...

  9. openshift 容器云从入门到崩溃之一《容器能解决什么问题》

    容器前时代 说到容器大多数人想到的就是docker,docker的迅速崛起使得使用容器的门槛大大降低了,我第一次接触docker还是14年,那时候作为一名运维部署应用还在大量使用虚拟化,从vmware ...

  10. Pandas 常见的基本方法

    说明:文章所有内容均截选自实验楼教程[Pandas 使用教程],想要查看教程完整内容,点击教程即可~ 前言: Pandas 是非常著名的开源数据处理工具,我们可以通过它对数据集进行快速读取.转换.过滤 ...