简述
PHP 团队于2020年11月26日宣布 PHP 8 正式发布!这意味着将不会有 PHP 7.5 版本。PHP8 目前正处于非常活跃的开发阶段,所以在接下来的几个月里,情况可能会发生很大的变化。我也分享一些研究PHP 8 的心得,希望PHPer大家一起共同进步。首先说一下最受关注的JIT。
JIT
由于 PHP 8 是一个新的大版本,因此升级版本,代码被破坏的可能性更高。如果项目始终保持运行 PHP 的最新版本,那么升级相对来说就会轻松很多,因为在 7. * 版本中,大多数重大更改均已弃用。除重大更改外,PHP 8 还带来了一些不错的新功能,比如说 JIT 编译器 , 联合类型 , 属性,以及更多。很多人可能对JIT有很深的误解,觉得引入JIT之后性能就能提高10倍跟V8平起平坐了,事实上不是这样的。JIT技术的水很深,动态语言的JIT尤其困难,V8的诞生几乎可以说是一个技术奇迹。以PHP社区的技术水平,我谨慎地不看好他们解决这个问题的能力,毕竟Facebook的HHVM也没有完全解决,最后是靠Hacklang补全PHP的语法功能之后才基本圆满解决的。
动态语言的JIT本质要解决的问题之中,生成汇编只是一小部分,对于弱类型和动态类型语言来说,优化内存布局也是重点。例如,对于JavaScript和Python来说,以前对象内部是一个HashMap,这种数据结构的访问效率比较低,导致访问对象的每个属性都很慢,在JIT之后会将它优化成类似C++的平铺式的布局,将属性的值按顺序放在特定的位置上,这就带来一些新的要求:
1. 没有类型标注的情况下,JIT只能猜测类型而无法肯定,那么使用优化的类型布局之前需要进行额外的检测,判断是否的确为预想的类型;
2. 属性的类型也需要进一步推测,使用时也需要检验;
3. JavaScript、Python乃至PHP都支持在对象创建之后为它添加新的属性。之前符合推测的类型后来添加或者删除了属性,要怎么处理?
除此之外,调用函数时候如何优化调用开销也是一个重点,本质上跟优化对象的内存布局是类似的,可以将传入参数看成是构建一个有多个属性的对象,每个属性的类型不同。局部变量也需要有选择性地优化到寄存器、栈和堆当中。
PHP在这里的优势是支持类型标注,缺点是所有Hacklang里面修改掉的部分:
1. 不支持泛型,尤其是array类型不支持泛型。将一个变量类型标注为array几乎没有任何帮助,PHP中的array可以是顺序表也可以是hashmap,还可以混着,value的类型也不确定,这些都对类型优化有很高要求。Hacklang就推荐废掉array改用vector等几个确定类型且支持泛型的数据结构。
2. reference这个功能,这个功能非常容易成为内存布局优化的障碍,也会阻碍JIT生成高效代码,尤其是数组中可以存储reference这件事,JIT编译器完全无法从字面上判断某条对array元素赋值的语句是否会影响环境中的其它变量的值。这也是为什么Hacklang直接删掉了这个功能。
3. 其他参考Hacklang的变更
之前版本(PHP7)抠解释器实现带来的性能优化也会是一个阻碍,JIT的时候这些都得放弃掉,因为内存布局不一样了,这样可能导致最初的时候许多应用JIT反而变慢。所以,PHP8如果解决不了这些问题,最大的可能是许多microbenchmark速度大幅上升,但整体应用性能持平,自娱自乐。
源码编译安装
1. 安装依赖
yum -y install autoconf freetype gd libpng libpng-devel libjpeg libxml2 libxml2-devel zlib curl curl-devel net-snmp-devel libjpeg-devel
2. oniguruma 依赖包
yum install autoconf automake libtool wget https://github.com/kkos/oniguruma/archive/v6.9.4.tar.gz -O oniguruma-6.9.4.tar.gz tar xf oniguruma-6.9.4.tar.gz && cd oniguruma-6.9.4 ./autogen.sh && ./configure --prefix=/usr make && make install
4.新建用户
userdel www groupadd www useradd -g www -M -d /data/www -s /sbin/nologin www &> /dev/null
5. 下载源码包
wget https://www.php.net/distributions/php-8.0.7.tar.gz
6. 解压
tar -zxvf php-8.0.7.tar.gz cd php-8.0.7
7. 编译和安装 (选择自己需要的安装)
./configure --prefix=/usr/local/php \ --with-config-file-path=/usr/local/php \ --enable-mbstring \ --enable-ftp \ --enable-gd \ --enable-gd-jis-conv \ --enable-mysqlnd \ --enable-pdo \ --enable-sockets \ --enable-fpm \ --enable-xml \ --enable-soap \ --enable-pcntl \ --enable-cli \ --with-openssl \ --with-mysqli=mysqlnd \ --with-pdo-mysql=mysqlnd \ --enable-mysqlnd-compression-support \ --with-pear \ --with-zlib \ --with-iconv \ --with-curl \ --build=arm-linux && make && make install
7. 开始配置
新增环境变量
vim /etc/profile ##最后增加 export PHP=/usr/local/php export PATH=$PHP/bin:$PHP/sbin:$PATH source /etc/profile
8. 配置PHP
cp php.ini-production /usr/local/php/etc/php.ini cp /usr/local/php/etc/php-fpm.conf.default /usr/local/php/etc/php-fpm.conf cp /usr/local/php/etc/php-fpm.d/www.conf.default /usr/local/php/etc/php-fpm.d/www.conf cp sapi/fpm/init.d.php-fpm /etc/init.d/php-fpm chmod +x /etc/init.d/php-fpm
9. 测试
[root@localhost www]# php -v PHP 8.0.7 (cli) (built: Jun 25 2021 10:10:16) ( NTS ) Copyright (c) The PHP Group Zend Engine v4.0.7, Copyright (c) Zend Technologies
编译过程错误解决
若在 configure 过程中,遇到提示 configure: error,留意看下方的错误详细信息。以下 列出了在配置过程中出现的错误情况之关键信息摘要,未列举到的其它错误情况,解决方 法如出一辙:
Error #1:
configure: error: Package requirements (libxml-2.0 >= 2.7.6) were not met:
No package ‘libxml-2.0’ found
解决方法:
yum install libxml2-devel.x86_64
Error #2:
configure: error: Package requirements (sqlite3 > 3.7.4) were not met:
No package ‘sqlite3’ found
解决方法:
yum install sqlite-devel.x86_64