PHP7的变化

引言

PHP7与PHP5版本相比有非常大的变化,尤其是在Zend引擎方面。为了提升性能,PHP7对Zend进行了深度优化,使得PHP的运行速度大大提高,比PHP5.0-5.6快了近5倍,同时还降低了PHP对系统资源的占用。

PHP7比较大的变化有:

抽象语法树

PHP是一种解释性语言,通过解析器来执行。

那么首先来看一下编译器与解释器的区别:读入源语言后,解释器和编译器都要进行词法分析、语法分析和语义分析,之后,二者开始有所分别。

  • 解析器与编译器的区别:

    • 解释器在语义分析后选择了直接执行语句;
    • 编译器在语义分析后选择将将语义存储成某一种中间语言,之后通过不同的后端翻译成不同的机器语言(可执行程序)。其存在一个预编译的过程。如下图所示:

      解释器与编译器的区别

  • PHP7之前的版本,代码解释过程:

    • PHP代码在语法解析阶段直接生成ZendVM指令,即在zend_language_parser.y中直接生成opline指令,使得编译器与执行器耦合在一起。
    • 编译生成的指令再供执行引擎使用,该指令是在语法指令直接生成的,若要更换执行引擎,怎需要修改语法解析规则;若PHP语法变化,但没有修改执行引擎,仍需要修改语法解析规则。其代码解析过程如下图:

      编译器PHP5

  • PHP7的代码解析过程:

    编译器PHP7

Native TLS

PHP5.x版本扩展中,有TSRM_CCTSRM_DC宏,用于线程安全。

PHP中有很多变量需要在不同函数间共享,多线程的环境下不能简单地通过全局变量来实现,为了适应线程的应用环境,PHP提供了一个线程安全资源管理器,将全局资源进行线程隔离,不同的线程之间互不干扰。

使用全局资源需要先获取本线程的资源池,这个过程比较占用时间,因此,PHP5.x通过参数传递的方式将本线程的资源池传递给其他函数,避免重复查找。这种方式需要所有函数接受资源池的参数(TSRM_DC宏所加的参数),这些参数传递不仅易遗漏参数,还是得代码不优雅

PHP7使用Native TLS(线程局部存储)来保存线程的资源池,简单来说就是通过__thread标识一个全局变量,这样这个全局变量就是线程独享的了,不同线程的修改不会相互影响。

指定函数参数、返回值类型

输入和输出参数必须是指定的数据类型,示例如下:

1
2
3
function foo(string $name): array {
return [];
}

zval结构的变化

Zval是PHP中最重要的数据结构之一(另一个比较重要的数据结构是hash table),它包含了PHP中的变量值和类型的相关信息。它是一个struct,在PHP5.x中,基本结构为:

1
2
3
4
5
6
7
struct _zval_struct {
zvalue_value value; /* value,变量的具体值 */
zend_uint refcount__gc; /* variable ref count,记录变量的引用计数(自动回收的基础) */
zend_uchar type; /* active type ,类型*/
zend_uchar is_ref__gc; /* if it is a ref variable,标识变量是否为引用 */
};
typedef struct _zval_struct zval;

变量的实际值,具体来说是一个zvalue_value的联合体(union),用来适配不同的变量类型:

1
2
3
4
5
6
7
8
9
10
typedef union _zvalue_value {
long lval; /* long value */
double dval; /* double value */
struct { /* string */
char *val;
int len;
} str;
HashTable *ht; /* hash table value,used for array */
zend_object_value obj; /* object */
} zvalue_value;

参考:PHP内核探索之变量(1)变量的容器-Zval

PHP5.x中引用计数是在zval中,而不是在具体的value中,这样一来,导致变量复制时需要复制两个结构,zval,zvalue_value始终是绑定在一起的。

  • 变化1:PHP7中将引用计数转移到具体的value中,这样更合理,因为zval只是变量的一个载体,可以简单地认为是变量名,而value才是真正的值,这个改变使得PHP变量之间的复制、传递更加简洁、易懂
  • 变化2:zval结构的大小由24byte减少到16byte,这PHP7能够降低系统的资源占用。

异常处理

PHP5.x中很多操作会直接抛出error错误,PHP7中将多数错误改为了异常抛出,这样就可以通过try catch捕捉到异常。这种新的异常处理方式使得错误处理更加可控。

HashTable的变化

HashTable,即哈希表,也称为散列表,它是PHP强大的array()类型的内部实现结构,也是内核中使用非常频繁的一个结构,函数符号表、类符号表、常量符号表等都是通过HashTable实现的。

PHP7中,HashTable结构的大小由72byte减小到56byte,同时,数组元素Bucket结构也由72byte减小到32byte。

执行器

execute_data、opline采用寄存器变量存储,执行器的调度函数为execute_ex(),这个函数复制执行PHP代码编译生成ZendVM指令。在执行期间会频繁地用到execute_data、opline两个变量。

PHP5.x中,这两个变量是由execute_ex()通过参数传递给各指令handle的。

PHP7中不再采用传参的方式,而是将execute_data、opline通过寄存器来存储,避免传参导致的频繁出入栈操作,同时寄存器相比于内存的访问速度更快。这个优化使得PHP的性能有了5%左右的提升。

新的参数解析

PHP5.x通过zend_parse_parameters()解析函数的参数,PHP7提供另外一种方式,同时保留原来方式,但是新的解析方式速度更快。

参考:秦朋 《PHP7内核剖析》第1.3节

推荐文章——关于PHP内部实现的文章:

  1. 给PHP开发者的PHP源码(1):源码结构
  2. 理解 PHP 内部函数的定义
  3. PHP 的变量实现
  4. 理解数组在PHP内部的实现

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/242326.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Git的下载安装

Git的下载安装 在你开始使用 Git 前,需要将它安装在你的计算机上。 即便已经安装,最好将它升级到最新的版本。 你可以通 过软件包或者其它安装程序来安装,或者下载源码编译安装。 或者 测试一下是否安装成功

Jacobi并行拆解【补充】

作者:桂。 时间:2018-04-24 22:04:52 链接:http://www.cnblogs.com/xingshansi/p/8934373.html 前言 本文为Jacobi并行拆解一文的补充,给出另一种矩阵运算的思路。 一、算法流程 对于复数相关矩阵R,通过矩阵变换,在…

PHP内核——内存管理

PHP中的变量是不需要手动释放的,内核帮我们实现了变量的内训管理,包括内存的分配与回收。本文主要介绍PHP中与内存相关的知识点,包括变量的GC机制、垃圾回收以及底层的内存池实现,除此还有一些线程安全相关的知识点。 变量的自动G…

买房贷款被拒,该如何补救?

买房贷款被拒,想要补救得先找到根源,然后才能对症下药。下面我们就来分析下房贷被拒的原因,以及补救的方法。一、征信不良一般在提交房贷资料之前银行会先查询申请人的信用记录,银行对征信的要求一般是连三累六,也就是…

配置有户名和邮箱

配置有户名和邮箱 按上下键,可以切换到历史命令。 修改信息 获取单独的信息 Git help 就是对各种命令进行查询 对help中的具体命令进行查询

这4种钱没有也要借,不能等

借钱?说起来好像是一件没有面子的事情,但是我们认真观察下人的一生,我们会发现,在不同的时间段,我们会面临各种各样的问题, 我们所处的环境都会不一样,有时候有些钱是必须要花的,即使…

注意:这些信用卡不激活也会产生费用

银监会规定,信用卡未经持卡人激活,不得扣收任何费用。因此很多人都以为信用卡不激活就不会产生费用,挺多留下一个征信查询记录,但这只针对普通的金卡、白金卡的情况,如果你申请的是特种卡、高端白金卡,钻石…

管理git项目

管理git项目 错误示范 第一步:想建立项目文件夹 第二步:进入到项目文件夹下 第三步:在项目文件夹下使用git命令 正确示范 第一步:创建项目文件 第二步:进入到项目文件夹下 第三步:初始化项目文件的…

有人说,如果有条件一定要远离穷人,你赞成吗?

我觉得应该远离穷人的环境及思想,而不是远离穷人。我记得有一位老师说过一句话:“一个人要走多远才能成功,关键是看与谁同行”。当时听这句的时候,觉得挺有哲理的,但并没有理解其中的深意,后来工作了多年之…

信用卡套现只要正常还款,银行是不是睁只眼闭只眼?

这要怎么说呢,目前没有法律规定说持卡人不能套现,套现要分恶意的还是非恶意的套现。只要你能够按时还款,你就是正常的消费,如果你套现之后出现逾期或不还,那你就是恶意套现,对于恶意套现,银行肯…

commit的作用

commit的作用 commit的作用:提交和保持的状态。会产生一个档案号。 没有被追踪时,不能使用commit(没有被提交)

银行理财不再保本保息,你还敢买吗?

2018年4月27日,《关于规范金融机构资产管理业务的指导意见》正式发布。这个指导意见的发布有几个大家最关心的点:一是银行的理财产品不能承诺保本保收益;二是银行不再承诺刚性兑付。所谓不在承诺保本保收益就是,以后购买银行理财产…

房贷是不是越多越久越好?

从理论上来说,房贷确实是越多、越久越有利,但是在操作的过程中需要根据自己的还款能力来定。为什么房贷越多越久越好?很简单的一个道理,物价每年都在上涨,而房贷不是每年都在涨,除非基准利率调整了才会跟着…

log追踪和追踪文件修改前后的区别

log追踪 :q表示退出 追踪文件修改前后的区别 只要没有git commit,就可以查看修改的区别

Vivado抓取信号

前言1111 FPGA调试需要抓取特定信号,一个直观的思路是:保存抓取的信号,事后分析/ 或者 导出实测数据,用作后续算法仿真验证。 本文简要记录数据的导出及读取。 一、信号导出 (1)把想要观测的信号线加入在线…

余额宝升级,限额限时解除,以后再也不用定闹钟抢破头了!

余额宝自2014年推出以来深得老百姓的喜欢,目前已经成为普通来百姓的理财神器,但是因为余额宝发展速度太快,累积的风险压力不断增加,所以余额宝一再限额,限购,限时。目前余额宝单个客户限额是10万元&#xf…

如何配置Git环境变量

如何配置Git环境变量 首先找到git的执行文件目录 右击选择属性 进入到bin文件下,复制执行文件路径 D:\git\Git\bin然后,搜索环境变量

征信报告上的逾期记录应该怎么清除?

正常情况下信用逾期是不能清除的,特殊情况除外。正常逾期不能申请消除,只能等时间消除人行征信中心规定,个人不良征信记录的记录时间是5年。但是这个5年是有前提条件的,5年时间是从你还清所有欠款的那天开始算起。比如你信用卡出现…

想创业没有资金,如何获得启动资金?

如果你项目好,就不怕没有资金。我们简单来说下几种创业资金的获取方式,当然不是每一种方式都适合所有人,具体要根据自己的条件来定。第一种:自有资金创业刚开始一般都以自有资金为主,因为你的项目刚起步,没…

比尔盖茨为什么能成为世界首富?

说到比尔盖茨的财富,很多人可能首先想到的是比尔盖茨精明的投资,因为这些年他通过跟巴菲特学投资,光靠投资就带来了超过700亿美元的财富,而微软所带来的财富只占其总财富的1/8左右。但我想说的是,投资确实给比尔盖茨带…