php7 开启zend-opcahe提升性能及原理解析

  首先:我们来了解一下php的执行过程解释 和什么是编译?

  一:执行过程的解释说明
 
  语言是人们进行沟通和交流的表达符号,每种语言都有专属于自己的符号,表达方式和规则。 就编程语言来说,它也是由特定的符号,特定的表达方式和规则组成。语言的作用是沟通,不管是自然语言,还是编程语言,它们的区别在于自然语言是人与人之间沟通的工具, 而编程语言是人与机器之间的沟通渠道。
  
  就PHP语言来说,它也是一组符合一定规则的约定的指令。 在编程人员将自己的想法以PHP语言实现后,通过PHP的虚拟机(确切的来说应该是PHP的语言引擎Zend)
       将这些PHP指令转变成C语言 (可以理解为更底层的一种指令集)指令,而C语言又会转变成汇编语言, 最后汇编语言将根据处理器的规则转变成机器码执行。这是一个更高层次抽象的不断具体化,不断细化的过程。
 
  什么是编译呢?
  
  从一种语言到另一种语言的转化称之为编译,这两种语言分别可以称之为源语言和目标语言。 这种编译过程通过发生在目标语言比源语言更低级(或者说更底层)。
 
   语言转化的编译过程是由编译器来完成, 编码器通常被分为一系列的过程:词法分析、语法分析、语义分析、中间代码生成、代码优化、目标代码生成等。 前面几个阶段(词法分析、语法分析和语义分析)的作用是分析源程序,我们可以称之为编译器的前端。 后面的几个阶段(中间代码生成、代码优化和目标代码生成)的作用是构造目标程序,我们可以称之为编译器的后端。
  一种语言被称为编译类语言,一般是由于在程序执行之前有一个翻译的过程, 其中关键点是有一个形式上完全不同的等价程序生成。而PHP之所以被称为解释类语言,就是因为并没有这样的一个程序生成, 它生成的是中间代码Opcode,这只是PHP的一种内部数据结构。编译型的语言有C ,C++ ,JAVA 等,而解释型语言则是 PHP

  PHP的执行流程(详细版):
  1:加载PHP文件
  2:词法分析
  3:将PHP代码转为有意义的语言片段(Token)
       4:语法分析
  5:将Token和符合文法规则的代码抽象成语法树
  6:将语法树编译生成对应的opcode(php对应的指令标识)
  7:执行
 
 PHP的执行流程(简略版-Zend执行过程):
  • 1.Scanning(Lexing) ,将PHP代码转换为语言片段(Tokens)

  • 2.Parsing, 将Tokens转换成简单而有意义的表达式(词法、语法、语义分析)

  • 3.Compilation, 将表达式编译成Opocdes

  • 4.Execution, 顺次执行Opcodes,每次一条,从而实现PHP脚本的功能,和机器指令运行相似。

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

  

  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 返回 

   Opcode cache 的目地是避免重复编译,减少 CPU 和内存开销,使其加载PHP文件更快。

 PHP的执行的核心是翻译出来的一条一条指令,也即opcode。

 Opcode是PHP程序执行的最基本单位。一个opcode由两个参数(op1,op2)、返回值和处理函数组成。PHP程序最终被翻译为一组opcode处理函数的顺序执行。

 参考资料:Opcode是啥以及如何使用好Opcache  https://www.zybuluo.com/phper/note/1016714

 

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

  

   Opcache 相关函数

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

  

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

  推荐的 php.ini 中 Opcache的配置

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

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

以下是官方的配置说明:

 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中,并且如果可能的话将被自动使用。
原文地址:https://www.cnblogs.com/xs-yqz/p/13178120.html