PHP中的OPCode和OPCache
概述
PHP作为一门动态脚本语言,其在zend虚拟机执行过程为:读入脚本程序字符串,经由词法分析器将其转换为单词符号,接着语法分析器从中发现语法结构后生成抽象语法树,再经静态编译器生成opcode,最后经解释器模拟机器指令来执行每一条opcode。
确切地说,分成以下四个步骤:
1. Scanning(Lexing) ,将PHP代码转换为语言片段(Tokens)
2. Parsing, 将Tokens转换成简单而有意义的表达式
3. Compilation, 将表达式编译成Opocdes(字节码)
4. Execution, 顺次执行Opcodes,每次一条,从而实现PHP脚本的功能。
一、OPCode
1、什么是opcode?
当一个 PHP 文件被解释执行的时候,首先是被编译成名为 opcode (CPU 专用的机器语言指令)的中间代码,然后才被底层的虚拟机执行。 如果PHP文件没有被修改过,opcode 始终是一样的。这就意味着编译步骤白白浪费了 CPU 的资源。
2、什么是opcode缓存?
此时 opcode 缓存就派上用场了。通过将 opcode 缓存在内存中,它能防止冗余的编译步骤,并且在下次调用执行时得到重用。一般执行过程是先检查文件的签名(signature)或者修改时间,以防文件有改动。
二、OPCache
1、什么是OpCache?
OPCache 是Zend官方出品的,开放*的 opcode 缓存扩展。PHP 5.5.0 及后续版本中已经绑定了 OPcache 扩展。
1)opCache的作用
主要是为了减少重复编译,从而减少CPU和内存的开销。
2)opcache缓存的内容
- OPCode
-
Interned String(可以理解为php请求生命周期中不需要释放的String,包括:变量名、类名、方法名、字符串、注释等)
2、OPCache的工作原理
Opcache工作原理其实是使用了共享内存机制,将需要缓存的内容放入到共享内存中,供其他进程使用。
因为Opcache在创建缓存的过程中不会阻止其他进程读取,所以在使用Opcache时要注意两点,不然会大量消耗资源:
1)不要给Opcache设置过期时间
2)不要在流量高峰期发布代码
3、OPCache的配置
1 //添加Opcache扩展 2 zend_extension=opcache.so 3 //开启Opcache 4 opcache.enable=1 5 //cli环境下启用Opcache 6 opcache.enable_cli=1 7 //浪费内存的上限,以百分比计,如果达到该上限,Opcache则会清空并重新生成缓存。默认5% 8 opcache.max_wasted_percentage=5 9 //配置共享内存存储大小,单位MB 10 opcache.memory_consumption=128 11 //用来存储临时字符串的内存大小,单位MB。这个配置就是上面说到的Opcache缓存的interned_string,它会在第一次使用到interned_string时缓存到共享内存中,供其他进程后续使用 12 opcache.interned_strings_buffer=8 13 //用于控制共享内存最多可以缓存多少个文件,该值最小范围是200,在php5.5.6版本之后,最大值是1000000 14 opcache.max_accelerated_files=4000 15 //设置缓存的过期时间,为0的话则每次都要检查 16 opcache.revalidate_freq=60 17 //如果启用,OPcache会在opcache.revalidate_freq设置的秒数去检测文件的时间戳(timestamp)检查脚本是否更新。如果这个选项被禁用(设置为0),opcache.revalidate_freq会被忽略,PHP文件永远不会被检查。这意味着如果你修改了你的代码,然后你把它更新到服务器上,再在浏览器上请求更新的代码对应的功能,你会看不到更新的效果 18 opcache.validate_timestamps=0 //所以像我上面说的,在大流量高并发场景下,该项不要启用,切记 19 //启用后,可以将依赖Zend引擎的内存管理模块一次释放全部请求变量的内存,而不是依次释放每一个已分配的内存块。 20 opcache.fast_shutdown=1 21 //启用文件缓存(设置缓存路径),这样Opcache就可以将Opcode缓存到文件中,实现跨php生命周期缓存 22 opcache.file_cache=/tmp
三、总结
合理的使用OPcahce将会减少Web服务器的CPU使用率,但是会增加一定的内存使用率。如果使用得到,这将会大大提高或服务端和PHP的吞吐量。
参考链接:
https://segmentfault.com/a/1190000021718693