推荐:《php8教程》
前言
即将发布的 php 8 最受大家关注的新特性就是引入了对 jit 的支持,我已经简单介绍了 jit 是什么,以及与 opcache 的区别,这里简单总结下:
jit 是在 opcache 优化的基础上结合 runtime 信息将字节码编译为机器码缓存起来现有的 opcache 优化不受任何影响,并且 php 的 jit 是在 opcache 中提供的jit 不是对 opcache 替代,而是增强,在启用 jit 的情况下,如果 zend 底层发现特定字节码已经编译为机器码,则可以绕过 zend vm 直接让 cpu 执行机器码,从而提高代码性能。看起来很高大上,不过 jit 主要针对 cpu 密集型操作优化效果明显,而目前主流的 php web 应用都是 io 密集型操作,那么 php 8 引入的 jit 对这些 web 应用的性能有没有提升呢?为此,特地编译安装了 php 8 alpha 版本,并分别对命令行应用(cpu 密集型操作)和 laravel 应用(io 密集型操作)进行了简单的基准测试来探个究竟。
准备一个 ubuntu 虚拟机
注:php 的 jit 只能在 x86 架构下生效,所以使用 intel cpu 的 pc、mac、linux 环境均可支持。
由于目前 php 8 还没有正式发布,只能下载源代码编译安装,所以需要准备一个 linux 环境作为测试环境。不少同学跟我反映没怎么在 windows 上演示过操作流程,所以今天我特地选择在 windows 10 专业版中通过 wsl 来安装 ubuntu 18.04 作为演示环境,这个比通过 virtual box 或者 vmware 安装虚拟机简单多了,不得不说,从 windows 10 开始,对开发者越来越友好了,虽然比起 mac 还是有些距离,毕竟 mac 是原生的类 unix 系统。
言归正传,安装 wsl 版 ubuntu 虚拟机 windows 官方提供了相应的文档:windows subsystem for linux installation guide for windows 10,照着做就好了,非常简单,在 windows 商店下载安装后,就可以点击启动按钮启动这个 ubuntu 虚拟机了:
打开后的界面是这样的,看起来和一个终端窗口差不多:
这个虚拟机使用起来的体验比传统的虚拟机要简单一些,比如直接可以调用 windows 宿主机的程序,比如 vs code,在虚拟机中通过 nginx 管理的 web 应用也可以直接从 windows 宿主机的浏览器访问,无需配置端口映射,所以用来作为本地 linux 测试开发环境很方便。
当然,如果你不想尝鲜的话,使用传统的虚拟机或者原生的 ubuntu 系统都可以。
演示项目初始化
接下来,我们需要通过上面打开的终端窗口在这个 ubuntu 虚拟机中安装 nginx,以及 php、composer,通过以下几个命令就可以搞定了:
sudo apt install nginxsudo apt install php php-zip php-mbstringsudo apt install composer
然后通过 composer 在 nginx 默认 web 根目录 /var/www 目录下安装用于演示的 laravel web 项目(下载速度慢可以配置 composer 全局镜像):
sudo composer create-project --prefer-dist laravel/laravel blog 6.* -vvv
初始化完成后,可以通过 php artisan serve 测试下这个项目访问是否正常。这里就不演示了。
编译安装 php 8 测试版
完成上述准备工作后,就可以开始 php 8 测试版本的编译安装了,首先,我们从 github 下载 php 8 测试版本源码(php 官网源码包下载太慢):
wget https://github.com/php/php-src/archive/php-8.0.0alpha2.tar.gz
解压并进入源码根目录:
tar zxvf php-8.0.0alpha2.tar.gzcd php-8.0.0alpha2
开始编译安装流程:
// 1、安装相关依赖库sudo apt install -y pkg-config build-essential autoconf bison re2c libxml2-dev \libsqlite3-dev libssl-dev libcurl4-openssl-dev libpng-dev libonig-dev libzip-dev// 2、生成 configure 文件./buildconf --force// 3、配置构建流程./configure --prefix=/usr/local/php8 \--with-config-file-path=/usr/local/php8 \--enable-mbstring \--enable-ftp \--enable-gd \--enable-mysqlnd \--enable-pdo \--enable-sockets \--enable-fpm \--enable-xml \--enable-soap \--enable-pcntl \--enable-cli \--enable-json \--enable-tokenizer \--enable-ctype \--enable-bcmath \--with-openssl \--with-pear \--with-zlib \--with-iconv \--with-curl \--with-zip// 4、构建make// 5、安装sudo make install
最后一步执行成功后,会有 php 8 安装成功的提示文本,你也可以通过如下命令验证安装成功:
当前 php 8 被安装到了 /usr/local/php8 这个目录下。
初始化配置文件
编译安装的 php 8 需要自行拷贝和设置配置文件,我们首先将基础配置文件 php.ini 从源代码目录拷贝到 php 的安装目录:
sudo cp php.ini-production /usr/local/php8/php.ini
由于 jit 是在 opcache 扩展中提供的,所以需要先启动这个扩展,打开 /usr/local/php8/php.ini,取消对如下配置项的注释(删除前面的分号即可):
zend_extension=opcache.soopcache.enable=1opcache.enable_cli=1
然后来初始化 php-fpm 的配置文件。
先把 php8.0-fpm 二进制文件拷贝到 /etc/init.d 目录下(还是在 php-8.0.0alpha2 源码目录下操作):
sudo cp sapi/fpm/init.d.php-fpm /etc/init.d/php8.0-fpmsudo chmod +x /etc/init.d/php8.0-fpm
进入 /usr/local/php8/etc 目录,初始化 php-fpm 配置文件:
cd /usr/local/php8/etcsudo cp php-fpm.conf.default php-fpm.conf
通过 vim 编辑器打开 php-fpm.conf,修改如下配置项(同时取消前面的分号注释):
pid = /run/php/php8.0-fpm.pid
然后进入当前目录下的 php-fpm.d 子目录:
cd php-fpm.dsudo cp www.conf.default www.conf
打开 www.conf,修改如下配置项(同时取消前面的分号注释):
user = www-datagroup = www-datalisten = /run/php/php8.0-fpm.socklisten.owner = www-datalisten.group = www-datalisten.mode = 0660
命令行应用基准测试
完成上述准备工作后,就可以正式开始测试工作了。
首先,我们来测试命令行应用,php 官方在源码中提供了一个基准测试文件,我们进入源码所在目录 php-8.0.0alpha2,通过如下命令测试不启动 jit 情况下代码运行情况:
/usr/local/php8/bin/php -d opcache.jit_buffer_size=0 zend/bench.php
运行结果如下(运行时间,单位为 s):
然后,再通过下面这条命令测试启动 jit 的情况下命令行代码的运行情况:
/usr/local/php8/bin/php -d opcache.jit_buffer_size=64m -d opcache.jit=1205 zend/bench.php
注:关于 opcache.jit_buffer_size 配置项比较好理解,而 opcache.jit 配置项对应配置值的每个数字代表不同含义,具体可以参考鸟哥的这篇博客:php 8 新特性之 jit 简介,里面讲得非常详细,一般对于命令行应用,将该配置值配置为 1205,对于 web 应用,配置为 1235 或者 1255。
最终运行结果如下:
可以看到,在 cpu 密集型操作的命令行应用中,启用 jit 与不启用相比,耗时降低了接近 60%,性能提升了 2 倍。
web 应用基准测试
接下来,我们以 laravel 演示项目为例,演示 php web 应用中启用 jit 与不启用性能有没有提升。
启动 php-fpm:
sudo /etc/init.d/php8.0-fpm start
在 nginx 中配置一个新的虚拟主机(/etc/nginx/sites-available/blog):
server { listen 80; server_name blog.test; root /var/www/blog/public; index index.html index.htm index.php; charset utf-8; location / { try_files $uri $uri/ /index.php?$query_string; } location = /favicon.ico { access_log off; log_not_found off; } location = /robots.txt { access_log off; log_not_found off; } error_page 404 /index.php; location ~ \.php$ { fastcgi_pass unix:/var/run/php/php8.0-fpm.sock; fastcgi_index index.php; fastcgi_param script_filename $realpath_root$fastcgi_script_name; include fastcgi_params; } location ~ /\.(?!well-known).* { deny all; }}
然后进入 /etc/nginx/sites-enable 目录,创建这个虚拟主机的软连接:
sudo ln -s /etc/nginx/sites-available/blog blog
启动 nginx:
sudo service nginx start
在 windows 系统的 c:\windows\system32\drivers\etc\hosts 文件中添加虚拟域名与主机地址的映射:
127.0.0.1 blog.test
此时可以在 windows 宿主机中通过浏览器访问对应的 laravel 项目,表示部署成功:
然后,我们还是在 windows 中,通过 ab 命令对 blog.test 首页进行压力测试(此时尚未启用 jit):
ab -n 10 -c 10 http://blog.test/
注:-n 表示总请求数,-c 表示最大并发请求数。
测试结果如下,重点关注 rps(每秒处理请求数):
最后,在 ubuntu 虚拟机中,打开 php 8 的配置文件 /usr/local/php8/php.ini,在 opcache 配置项下新增 jit 配置:
opcache.jit=1235opcache.jit_buffer_size=64m
配置完成后,重启 php-fpm 服务,再次回到 windows 宿主机,通过 ab 命令对 http://blog.test 页面进行压力测试:
ab -n 10 -c 10 -s 60 http://blog.test/
注:-s 表示超时时间。
运行结果如下:
可以看到在 io 密集型操作的 web 应用中,启用 jit 与不启用相比,性能不但没有提升,反而有 10% 左右的损耗,至少在 laravel 应用中是如此。
小结
当然,这里的测试仅限于的 ubuntu 虚拟机环境(windows wsl 版,配置是 8c8g),并且我也只是将 jit 参数调整为官方建议的参数,没有做更多的对比测试,但是可以肯定的是 jit 对 cpu 密集型操作优化效果很好,对 web 应用性能是否有提升,取决于你的环境和配置的调优,因此 jit 对 io 密集型操作应用的性能优化效果有限,更适用于 cpu 密集型操作场景的性能优化,比如图像处理、机器学习等。
以上就是php 8新特性之jit对php应用性能的影响的详细内容。