位置: 编程技术 - 正文

深入理解PHP内核(一)(php8底层内核)

编辑:rootadmin

推荐整理分享深入理解PHP内核(一)(php8底层内核),希望有所帮助,仅作参考,欢迎阅读内容。

文章相关热门搜索词:深入理解php内核程序,php内涵,深入理解php内核设计,php内涵,php7内核剖析,深入理解php内核设计,深入理解php内核程序,深入理解php内核工具,内容如对您有帮助,希望把文章链接给更多的朋友!

PHP作为一门简单而强大的语言,能够提供很多Web适用的语言特性。从实践出发,继弱类型变量原理探究后,本文继续带领大家深入理解php内核。

最近,和一个网友交流的时候,给我提了一个非常奇怪的问题。那就是,在一个运算中,加了一个引用之后,发现性能慢了一万倍。在我的脑海里面,引用是一个非常容易出错的问题,特别是PHP里面的引用,有非常多的陷阱。因为,以前专门研究过这一块PHP的源代码,所以,我可以比较清晰的解析引用到底是怎么一回事,希望,读了我这篇文章,能彻底理解这个问题。如果,有任何疑问,或者有一些你想了解的问题,可以给我留言。

先来看一段代码:

如果你完这个代码,能说出,为了reffer 和 noreffer会差一万倍的性能,那下面的也就没有必要往下看了。这篇博客针对的是,PHP的新手。你可以运行一下这个代码试试看,的确差了一万倍。当然,那个网友遇到的问题的代码要比上面的复杂,上面的代码是我为了说明问题,特意简化的。或许你已经从代码里面看出问题了,但是,至于为什么会这样。我想,还是有必要分析一下。这样,以后,在使用PHP的时候,才不会犯相同的错误。

PHP为了减少复制,采用了一种copy on writer的机制。我想,这是一种非常常见的机制,你也一定听说过。比如,gcc 的 stl string 的实现,就是采用这样的机制,字符串赋值,不是真正的复制,而且,在修改的时候才会进行复制。我们先来举个最简单的例子:

$a 是一个非常大的字符串,如果 $b = $a 的时候,进行复制,那要耗费很多内存 和 cpu,这样非常的不划算,万一,下面的代码并不修改$a 和 $b 那复制根本没有必要。当然,$a 在后面又被修改了,这个时候,必须进行复制了,否则就不符合逻辑了。但是,现在问题来了,怎么知道,$a 在修改的时候,要进行复制呢,必须要有这样一个标记。方法就是采用引用计数。引用计数还被用来进行内存的管理。

基本的流程是这样的:

1: 创建一个变量,可以保存 个 0 的这样一个字符串。

2: 创建一个变量符号 a ,这个变量符号引用 这个变量。注意,变量符号 和 变量不是一回事情,这两者是分离的。

如果从C语言的角度来说,PHP大概完成这样一件事情:

active_symbol_table 是PHP的一个符号表,所有能访问到的变量都在这个里面,他是一个哈希表。var 这个变量,保存了 个 0 这个字符串。而且是zval的结构,zval的结构如下:

zvalue_value 是一个联合,可以保存 long, double, 字符串,哈希表(PHP Array),还有就是 对象。也就是所有的PHP的类型。 zval 其实 就是 对 zvalue_value ,加入了类型type 和 引用is_ref,引用计数refcount三个功能。这就是PHP中的普通变量。要是用PHP做比较大型的东西,就会发现,内存占用非常厉害。就是因为,他一个变量 不是 传统C语言的那个变量了,它加了很多东西。

好了,第一句完成了,下面是第二句。第二句很简单,会产生一个新的变量符号b,把他加入 active_symbol_table ,但是不会增加新的一个变量,而只是,refcount++。赋值就完成了。如图:

首先我们要注意的是,a ,b 只是一个符号,他是active_symbol_table 表里面的一个key,都有一个指针指向一个zval,所以,a 和b 在 C语言层面上是完全一致的。我们就得出PHP变量第一定律:

深入理解PHP内核(一)(php8底层内核)

PHP变量第一定律:如果两个变量指向同一个zval,那么这两个变量是无差别的。也就是说,任何对a 的操作 相对b 都是对称的。这里的对称,是这样理解的。就是镜子中的你,而不是等同。比如,对 a 进行 赋值,a 就会产生 copy。同样的,如果对b进行赋值,也会进行相同的操作,那就是b产生一个copy。也就是说,a 和b的行为是一样的。

第三句,当writer发生的时候,PHP会判断一下refcount 是否大于2,如果大于2,那么就复制一下zval,然后,把原来那个zval refcount--。这就是copy on writer 的全部了,你一定觉得,这一切你都是非常的熟悉,你都懂。

但是,PHP不仅仅是copy on writer 这样简单,它还有一个引用的问题。引入引用的概念,这样,问题就变的有些复杂了。因为,引用这个标记,意思就是说,writer 的时候,你也不需要复制。这样,会修改原来的那个变量。从我们在学校里面以前经常学习的哲学上来说,这是一对矛盾。他们是对立的,又是统一的,各有各的用处。所谓,存在的就是合理的。

好,下面我们来看看这对矛盾,我们只考虑两种组合的情况。多种组合都是类似的。两种组合的话,就是赋值在前,引用在后。

或者 引用在前,赋值在后。我们会分别讨论,先来看:就是赋值在前,引用在后的情况。

$b = $a, 是copy on writer 行为的 赋值。而 $c 和 $a 是引用赋值。我们假设在上面这样的情况下,我们可以用一个zval表示,也就是不需要复制,那么情况是这样的:

根据我们的PHP变量第一定律,那,就是说,a,b,c的操作是对称的,但是非常明显,对 b 操作要产生复制行为,而对a操作不会产生复制,操作行为不相同,和第一定律矛盾。也就是说,要使得上面的操作没有矛盾,必须,进行分离。分离的原则就是,谁制造矛盾,谁复制。显然是 第三句话,$c = &$a; 在制造矛盾。所以,内部变量的复制过程如下图:

上面情况是赋值在前,引用在后的情况。还有一种情况是,引用在前赋值在后:

按照PHP变量的第一定律,a,b,c 必须进行分离,才能保证定律的正确。可以发现,b 和 a 明显是一伙人,就是说,b 和 a 的操作是对称的,他们可以指向同一个zval ,而c 的行为和 a,b 不一样,改变c 需要进行复制。看到这里,我想,如果你看懂了的话,为什么刚开始,贴出来的那段代码的,那个两个count差异如此之大,你也应该明白了。当我和那个网友讨论的时候,它最后说,那这样的话,PHP设计的不好,我完全可以,$c先不进行复制,等c被write 了,再进行复制。看来要说懂一个东西,还是一件很难的事情,好好想想那个PHP第一定律吧。你可以假设不进行分离,c指向同一个zval,所以,c 和 a,b的行为是一样的,是is_ref = 1,所以,c 不会进行复制。最后一种内部执行情况可以用下图表示:

我以前也进行搞混这个引用,现在,你可以用那个第一定律来分析所有的情况了。PHP内核分析的文章,以后我还会写一些,如果你想深入了解PHP的某些方面,可以给我留言。

最后再补充一点,也是一个隐性的错误。

这里,没有显示的引用,但是这里隐藏了一个引用。PHP会自动创建一个引用全局变量 $bigarray 的代码,如果你在这里使用count,那么这个效率会非常的慢。最好直接通过$GLOBAL 数组进行引用。

下面文章将给大家介绍深入理解php内核二之SAPI探究,希望大家继续关注哦。

深入理解PHP内核(二)之SAPI探究 在上篇文章给大家介绍了深入了解PHP内核(一),相信大家通过本文多多少少都学到些知识吧,关于php内核知识继续关注本篇文章。SAPI是ServerApplicationProgra

如何使用PHP Embed SAPI实现Opcodes查看器 PHP提供了一个EmbedSAPI,也就是说,PHP容许你在C/C++语言中调用PHP/ZE提供的函数。本文就通过基于EmbedSAPI实现一个PHP的opcodes查看器。首先,下载PHP源码以

谈谈你对Zend SAPIs(Zend SAPI Internals)的理解 SAPI:ServerabstractionAPI,研究过PHP架构的同学应该知道这个东东的重要性,它提供了一个接口,使得PHP可以和其他应用进行交互数据。本文不会详细介绍每

标签: php8底层内核

本文链接地址:https://www.jiuchutong.com/biancheng/276037.html 转载请保留说明!

上一篇:在PHP中使用FastCGI解析漏洞及修复方案(在php中使用什么获取文件的修改时间)

下一篇:深入理解PHP内核(二)之SAPI探究(php的核心)

  • 个人独资企业是否享受六税两费政策
  • 免税收入是什么票据类型
  • 实收资本印花税怎么申报税目
  • 所得税汇算清缴补税的会计处理
  • 印花税核定征收管理办法
  • 自己提供原材料让别人加工
  • 空白增值税专用发票丢失罚款
  • 原会计收入准则最新
  • 事业单位库存物品
  • 专项科研经费
  • 收到法人的借款
  • 发票冲销后还能用吗
  • 进口的原材料没有发票
  • 利息收入汇算清缴
  • 办公室购置空调的词语
  • 公司获得奖金计入什么科目
  • 个体工商户有公户吗?
  • 总公司与分公司的账务处理销售
  • 公司为员工负担个税怎么做账
  • 取得带息应收票据时,企业应于期末计算票据利息
  • 代理记账公司收费标准
  • 一般纳税人开普票税率是3%还是13%
  • 去年的成本今年入账会计分录
  • 金蝶怎么一次性删除所有分录
  • 六月雪的养殖方法和注意事项
  • 为什么电脑连上蓝牙耳机却是外放
  • bios设置内存频率后黑屏
  • 查看电脑系统版本
  • bigfile是什么意思
  • php __invoke
  • 代扣代缴个税手续费返还会计分录
  • phpsql防注入代码
  • php实现留言板功能
  • laravel日志管理系统
  • laravel 自定义guard
  • 金蝶迷你版怎么安装
  • 质量事故发生后,有责任就所发生的质量事故
  • 连续3个月没有休息怎么发朋友圈文案
  • 进项大于销项附加税怎么处理
  • 电子税务局税种核定在哪里
  • 织梦下载站源码带采集
  • python的元组有什么用
  • python time.ctime()如何做时间加减法
  • 公司用印制度
  • 个税代扣代缴手续费返还需要缴纳增值税吗
  • 在windowsxp的应用程序中,经常
  • 出口退税款计入营业外收入
  • 一般纳税人收到的普票可以抵扣吗
  • 非广告性质的赞助支出调增还是调减
  • 股东权益合计等于净资产吗
  • 个体工商户财务怎么做账
  • 科技项目扶持资金
  • 从公司账户转给他人私户1万元以内需要扣多钱的税
  • 事业单位职工福利费
  • 职工福利费和工会经费
  • 非税收入定额票据是什么
  • 员工体检的发票在哪里开
  • sql 行号
  • SQL Server的通用分页存储过程 未使用游标,速度更快!
  • MySQL PXC构建一个新节点只需IST传输的方法(推荐)
  • windows无法启动MySQL80服务
  • win10执行数据保护如何开启
  • 系统审核策略配置
  • centos nohup
  • windows xp.exe
  • linux getuid
  • linux vmware命令行
  • windows8的ie浏览器在哪
  • Unable to execute dex: Multiple dex files define Lorg/cocos2dx/lib/Cocos2dxAccelerometer
  • js操作dom节点的方法
  • jQuery Ajax 实现在html页面实时显示用户登录状态
  • 使用vue开发手机app
  • unity shader cull off
  • python支持中文字符
  • 数字图像处理软件idl和matlab有什么异同点
  • 国税局公告2019年43号
  • uk开票软件如何赋码
  • 广东电子税务局中山税务局网
  • 云南税收主要经济来源
  • 天津静海离天津市区多远
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

    网站地图: 企业信息 工商信息 财税知识 网络常识 编程技术

    友情链接: 武汉网站建设