PHP的垃圾回收机制

PHP的垃圾回收机制一、原理 php5和php7的垃圾回收机制都是利用引用计数。 二、php5和php7不同点 1、PHP5标量数据类型会计数,PHP7标量数据类型不再计数,不需要单独分配内存。 2、PHP7的zval…

PHP的垃圾回收机制

PHP的垃圾回收机制

 

一、原理

php5和php7的垃圾回收机制都是利用引用计数。

二、php5和php7不同点

1、PHP5标量数据类型会计数,PHP7标量数据类型不再计数,不需要单独分配内存。

2、PHP7的zval 需要的内存不再是单独从堆上分配,不再自己存储引用计数。

3、PHP7的复杂数据类型(比如数组和对象)的引用计数由其自身来存储。

三、变量在zval的变量容器中结构

v2-8f18e9b97b4ef9b5ab793b1a50f46326_720w.png

zval中,除了存储变量的类型和值之外,还有is_ref字段和refcount字段 1、is_ref:是个bool值,用来区分变量是否属于引用集合。 2、refcount:计数器,表示指向这个zval变量容器的变量个数。 

代码100分

四、PHP5.3标量在zval容器例子

注意:

php5.3中将一个变量 = 赋值给另一个变量时,不会立即为新变量分配内存空间,而是在原变量的zval中给refcount加1。

只有当原变量或者发生改变时,才会为新变量分配内存空间,同时原变量的refcount减 1 。

当然,如果unset原变量,新变量直接就使用原变量的zval而不是重新分配。

&引用赋值时,原变量的is_ref 加1. 如果给一个变量&赋值,之前 = 赋值的变量会分配空间。

代码100分<?php $a = 1; xdebug_debug_zval("a"); echo PHP_EOL; $b = $a; xdebug_debug_zval("a"); echo PHP_EOL; $c = &$a; xdebug_debug_zval("a"); echo PHP_EOL; xdebug_debug_zval("b"); echo PHP_EOL; 结果如下: a:(refcount=1, is_ref=0),int 1 a:(refcount=2, is_ref=0),int 1 a:(refcount=2, is_ref=1),int 1 b:(refcount=1, is_ref=0),int 1

 

五、PHP7.X 标量在zval容器例子

<?php $a = 1; xdebug_debug_zval("a"); echo PHP_EOL; $b = $a; xdebug_debug_zval("a"); 结果如下:可以看到标量(布尔,字符串,整形,浮点型)不再计数了

v2-7f44154545a219edbcc9d17116855ca8_720w.jpg

六、PHP5.3复合类型数组和对象在zval容器例子

代码100分<?php $a = array( "meaning" => "life", "number" => 42 ); xdebug_debug_zval( "a" ); echo PHP_EOL; class Test{ public $a = 1; public $b = 2; function handle(){ echo "hehe"; } } $test = new Test(); xdebug_debug_zval("test"); 结果如下:可以看出,数组用了比数组长度多1个zval存储。数组分配了三个zval容器:a meaning number a:(refcount=1, is_ref=0), array "meaning" => (refcount=1, is_ref=0), string "life" (length=4) "number" => (refcount=1, is_ref=0), int test:(refcount=1, is_ref=0), object(Test)[1] public "a" => (refcount=2, is_ref=0), int public "b" => (refcount=2, is_ref=0), int

v2-9c13c9259a50f918cb56663751698616_720w.jpg

七、PHP7.X复合类型数组和对象在zval容器例子

<?php $a = array( "meaning" => "life", "number" => 42 ); xdebug_debug_zval( "a" ); echo PHP_EOL; class Test{ public $a = 1; public $b = 2; function handle(){ echo "hehe"; } } $test = new Test(); xdebug_debug_zval("test")
结果如下:

可以明显的看到数组a的refcount=2,后经测试发现数组的refcount都是从2开始的

v2-bce30a98a9b5192d487ab45279a92ac9_720w.jpg

八、循环引用问题

1、PHP7.1效果

<?php $a = array("life"); xdebug_debug_zval( "a" ); echo PHP_EOL; $a[] = &$a; xdebug_debug_zval("a"); 

v2-b8561e2a2611c586184a54592a5a053f_720w.jpg

可以看到,箭头方向表示的就是递归循环引用了

v2-7370102e36504e5f90a1a64020a23781_720w.jpg

说明:

在5.2及更早版本的PHP中,没有专门的垃圾回收器GC(Garbage Collection),引擎在判断一个变量空间是否能够被释放的时候是依据这个变量的zval的refcount的值,如果refcount为0,那么变量的空间可以被释放,否则就不释放,这是一种非常简单的GC实现。现在unset ($a),那么array的refcount减1变为1.现在无任何变量指向这个zval,而且这个zval的计数器为1,不会回收。

结果:

尽管不再有某个作用域中的任何符号指向这个结构(就是变量容器),由于子元素“1”仍然指向数组本身,所以这个容器不能被清除。因为没有另外的符号指向它,用户没有办法清除这个结构,结果就会导致内存泄漏。

在php5.3的GC中,针对的垃圾做了如下说明:

①如果一个zval的refcount增加,那么此zval还在使用,肯定不是垃圾,不会进入缓冲区

②如果一个zval的refcount减少到0, 那么zval会被立即释放掉,不属于GC要处理的垃圾对象,不会进入缓冲区。

③如果一个zval的refcount减少之后大于0,那么此zval还不能被释放,此zval可能成为一个垃圾,将其放入缓冲区。PHP5.3中的GC针对的就是这种zval进行的处理。

开启/关闭:垃圾回收机制可以通过修改php配置实现,也可以在程序中使用gc_enable() 和 gc_disable()开启和关闭。

九、垃圾回收算法

 

1、对每个根缓冲区中的根zval按照深度优先遍历算法遍历所有能遍历到的zval,并将每个zval的refcount减1,同时为了避免对同一zval多次减1(因为可能不同的根能遍历到同一个zval),每次对某个zval减1后就对其标记为“已减”。

2、再次对每个缓冲区中的根zval深度优先遍历,如果某个zval的refcount不为0,则对其加1,否则保持其为0。

3、清空根缓冲区中的所有根(注意是把这些zval从缓冲区中清除而不是销毁它们),然后销毁所有refcount为0的zval,并收回其内存。

如果不能完全理解也没有关系,只需记住PHP5.3的垃圾回收算法有以下几点特性:

1、并不是每次refcount减少时都进入回收周期,只有根缓冲区满额后在开始垃圾回收。

2、可以解决循环引用问题。

3、可以总将内存泄露保持在一个阈值以下。

 

1

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
转载请注明出处: https://daima100.com/8898.html

(0)
上一篇 2023-02-19
下一篇 2023-02-19

相关推荐

  • 本地库还原至阿里云RDS服务器

    本地库还原至阿里云RDS服务器摸索了很久,在此也感谢阿里云售后兄弟的支持。 1、 首先得要有个阿里云账号,已经购买RDS数据库(本文针对SQL Server)且已经开通阿里云OSS服务。 2、 本文档适用于以下版本的实例: RDS

    2022-12-20
    108
  • 数据库的结构_数据库的结构包括文本吗

    数据库的结构_数据库的结构包括文本吗学习重点 RDBMS 通常使用客户端/服务器这样的系统结构。 通过从客户端向服务器端发送 SQL 语句来实现数据库的读写操作。 关系数据库采用被称为数据库表的二维表来管理数据。 数据库表由表示数据项目

    2023-04-25
    109
  • 以Python Twisted为核心的网络编程

    以Python Twisted为核心的网络编程在现代的互联网世界中,网络编程是最基本的技能之一。Python是一种强大的编程语言,以简洁、清晰、优雅的代码而著称。而Twisted作为Python中最为流行的网络编程框架之一,能够帮助开发人员快速实现复杂的网络应用程序。

    2024-05-07
    15
  • ORACLE RMAN自动备份还原脚本设计

    ORACLE RMAN自动备份还原脚本设计很多时候,我们DBA需要定时对生产环境进行整体备份,并恢复到测试环境,供开发人员调试或测试,如果数据量比较大的情况下,RMAN方式比较高效省时,下面策略是在生产环境部署备份任务,并在测试模拟环境进行…

    2022-12-22
    102
  • 同步到网盘的资料在哪里找_电脑文件同步云端

    同步到网盘的资料在哪里找_电脑文件同步云端文件同步网盘中那个同步excel好用?与Word、Excel、PPT等Office应用联系最为紧密的应当就是OneDrive了,它们都是微软旗下的产品,OneDrive与Office办公软件的融合,…

    2023-04-11
    118
  • 时序数据库是什么_主流时序数据库

    时序数据库是什么_主流时序数据库时序数据库经常应用于机房运维监控、物联网IoT设备采集存储、互联网广告点击分析等基于时间线且多源数据连续涌入数据平台的应用场景,InfluxDB专为时序数据存储而生,尤其是在工业领域的智能制造,未来应

    2023-04-26
    107
  • 成都哪里可以开房租费发票-中国-新闻网「终于解决」

    成都哪里可以开房租费发票-中国-新闻网「终于解决」成都哪里可以开房租费发票【152 * 9б 28 * 21 б9】陈生,诚、信、合、作,保、真、售、后、保、障、长、期、有、效。adb的全称为Android Debug Bridge,是Androi…

    2023-01-31
    107
  • 与oracle 有关的那点事「终于解决」

    与oracle 有关的那点事「终于解决」常用操作 1.查看创建表参数 提取完整的DDL: SELECT DBMS_METADATA.GET_DDL(&#39;TABLE&#39;,&#39;table_name&am

    2023-03-08
    107

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注