PHPweb服务打造强悍性能之php-fpm模式的opcache开启和swoole模式

分享于:2020-11-04 15:35:04

编译与解释


了解opcache前,先了解下编程语言的编译与解释。


对于一个编译型程序,它的编译和执行是分开的,先编译成二进制可执行文件,然后再次执行。


C语言是编译型语言,写完程序代码后,不能运行。需要使用编译器把源程序的每一条语句都编译成机器语言(机器代码,即二进制),并保存为二进制文件。这样计算机直接运行编译好的二进制文件,速度很快。只要源程序代码不做修改,无需重新编译,每次执行程序时只需要执行编译好的二进制文件就好。


对于PHP、Python等等很多脚本语言都属于解释型语言,写完代码以后就可以运行。它们是怎么运行的?


每次执行时,需要借助一个解析器,先把字符代码编译为易于执行的中间代码(不是机器代码,这种中间代码与机器代码不同,中间代码的解释是由软件支持的,不能直接使用硬件。然后再使用可以理解中间代码的解析器逐一将源程序的语句解释成可执行的机器指令。


总述下,解释型语言每次执行时才一条一条地解释成机器语言给计算机来执行,而不是将源程序预先编译好目标代码后再执行。所以运行速度不如编译后的程序运行得快。


至于Java,可以说它是编译型的。因为所有的Java代码都是要编译的,.java不经过编译就什么用都没有。 也可以说它是解释型的,因为java代码编译成.class后不能直接运行,它是解释运行在JVM上的,所以它是解释运行的。但是,现在的JVM为了效率,都有一些JIT优化。它又会把.class的二进制代码编译为本地的代码直接运行,所以,又是编译的。


opcode


opcode就是PHP的中间代码(操作码),opcode不能直接执行,要靠解析器来进行执行,PHP的解析器是Zend引擎。


2020-11-04_170115.png


Zend引擎默认做法,是先编译为opcode,然后再逐条执行。PHP在未开启opcache之前,就会每执行一次就翻译一次,因而效率低下。


opcache


什么是Opcache呢?opcache = Opcode + cache。


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


 PHP的正常执行流程如下:

1128628-20180504142714761-711951956.png


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

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


1128628-20180504142714761-711951956.png


Opcode cache 的目地是避免重复编译,减少 CPU 和内存开销。


opcache具体怎么开启使用,参考《opcache的配置与使用


开启opcache后,就会大幅度提高PHP程序性能,减少响应时间。


从PHP7.4开始,有个新的特性:preload(预加载),可以将文件提前加载到内存当中,提升 PHP 性能,开preload的前提是开opcache。

php7.4 preload(预加载)知识介绍


swoole


大部分情况下,我们使用PHP做web开发,最佳搭配就是nginx+php-fpm。FPM效率并不高,为什么还那么多人选择FPM模式搭建web程序?


因为在FPM下不需要关心内存泄漏!内存泄漏是所有程序员的噩梦,内存泄漏(Memory Leak)是指程序中已动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。


fpm下为什么不会内存泄漏?这是因为每次请求页面创建的数据不会常驻内存,在脚本执行完毕后所有的数据内存都会被释放掉。php_request_shutdown就是用来释放每次请求时的内存空间,所以使用php-fpm不用管内存泄漏,这是PHP独创的。


但是这样会有什么问题呢?就是性能会受到影响。


当第一次请求时,初始化的数据(比如全局变量,静态成员,对象等数据),其实在第二次,第三次,以后多次的请求中只要代码不做修改数据都不会变的。然而每次请求后都释放掉,下次请求再初始化,严重地浪费系统资源,这也就造成性能慢的重要原因。


深入理解PHP的内存泄漏


opcache提高性能,只是从代码解析这块做得优化,它并没有实现数据常驻内存。还好现在PHP出现了新的一些扩展,比如这个swoole。


swoole可以让PHP在cli下搭建web服务,取代php-fpm模式。它的一大优势,就是可以让第一次初始化的数据常驻内存,以后的请求中都可以复用。这也就是swoole性能高的原因。


在cli下执行PHP是不调用php_request_shutdown函数,这就需要我们自己注意下内存泄漏的问题。


您想更高提升PHP的性能,可以去尝试学习下swoole,官网是www.swoole.com,使用swoole搭建web服务,是需要多下些功夫了解它的文档,和扩充相关的知识。