【黄啊码】垃圾回收可以赚钱,那php的垃圾回收机制你懂多少?

大家好,我是黄啊码,相信java的垃圾回收机制,任何java入门的码农们多多少少已经接触过了,那么php的垃圾回收机制又有多少知道,知道的评论区打个1呗。

好了,废话不多说,开干!!!

目录

什么是垃圾回收?

php为什么需要垃圾回收?

Java和PHP的垃圾回收机制对比:

我们这里只讲两个大版本的php回收机制【php5和php7】

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

2、php5和php7的垃圾回收机制异同:

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

PHP5.3标量在zval容器例子

 PHP7.X 标量在zval容器例子

最后备注说明:

垃圾回收对性能的影响

什么是垃圾回收?

"回收旧手机,旧热水器,旧手表。。。"是这个吗?你要这么说,我一定会问:这是干垃圾还是湿垃圾?哈哈。pia,清醒点把你,咱们这是在说编程语言,在使用 C 语言的时候,我们都要手动使用 free 来释放内存,在 C 之后的大部分编程语言都会自带一个垃圾回收之类的处理能力,也就是我们今天要说的垃圾回收机制,也称为 GC 。在有 GC 能力的开发语言中,我们不需要去关心什么时候释放内存,甚至我们完全不需要去了解这一块的内容,因为这些语言在底层已经帮我们处理好了关于内存释放的问题。

php为什么需要垃圾回收?

我们的开发者在不断地操作内存。相应地,如果我们继续增加新变量,内存将继续增加,如果没有良好的机制,内存将无限制地增加,最终填满所有内存。这会导致内存泄漏。但是,在日常开发中,除非一次性加载大文件,否则很少看到内存溢出错误。这就是垃圾收集机制的作用。

Java和PHP的垃圾回收机制对比:

Java 种的垃圾回收机制,大家肯定都有所了解,比如如何确定垃圾,有两种算法,引用计数法和可达性分析算法。Java 中使用的是可达性分析算法,而 PHP 使用的引用计数算法。我们都知道引用计数算法较难处理循环引用的问题,PHP 这波奇怪的操作可太秀了,那 PHP 的垃圾回收原理是怎么样的?

我们这里只讲两个大版本的php回收机制【php5和php7】

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

原理: 给对象添加一个引用计数器,每当有一个地方引用它,计数器的值就加一。每当有一个引用失效,计数器的值就减一。

如果一个变量 value 的 refcount 减一之后等于 0,此 value 可以被释放掉,不属于垃圾。垃圾回收器不会处理 。

如果一个变量 value 的 refcount 减一之后还是大于 0,此 value 被认为不能被释放掉,可能成为一个垃圾。

垃圾回收器将可能的垃圾收集起来,等达到一定数量后开始启动垃圾鉴定程序,把真正的垃圾释放掉。

2、php5和php7的垃圾回收机制异同:

  • PHP5标量数据类型会计数,PHP7标量数据类型不再计数,不需要单独分配内存
  • PHP7的zval 需要的内存不再是单独从堆上分配,不再自己存储引用计数。
  • PHP7的复杂数据类型(比如数组和对象)的引用计数由其自身来存储。

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

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

PHP5.3标量在zval容器例子

 注意:php5.3中将一个变量 = 赋值给另一个变量时,不会立即为新变量分配内存空间,而是在原变量的zval中给refcount加1。 只有当原变量或者发生改变时,才会为新变量分配内存空间,同时原变量的refcount减 1 。

当然,如果unset原变量,新变量直接就使用原变量的zval而不是重新分配。&引用赋值时,原变量的is_ref  加1.  如果给一个变量&赋值,之前 = 赋值的变量会分配空间。

<?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');结果如下:可以看到标量(布尔,字符串,整形,浮点型)不再计数了

最后备注说明:

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

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

在php5.3的GC中,针对的垃圾做了如下说明:
    1:如果一个zval的refcount增加,那么此zval还在使用,肯定不是垃圾,不会进入缓冲区
    2:如果一个zval的refcount减少到0, 那么zval会被立即释放掉,不属于GC要处理的垃圾对象,不会进入缓冲区。
    3:如果一个zval的refcount减少之后大于0,那么此zval还不能被释放,此zval可能成为一个垃圾,将其放入缓冲区。PHP5.3中的GC针对的就是这种zval进行的处理。

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

垃圾回收对性能的影响

前文说过,垃圾回收在根缓冲区满了之后会马上执行。其中也会进行两次的深度遍历,这就不可避免的带来了性能的消耗。毕竟算法的执行都是需要耗时的。不过相对于内存溢出这种毁灭性的错误来说,垃圾回收带来的性能损耗基本上是可以忽略不计的。

好了,今天的课程学到这里,有问题的留个言,别忘了一键三连,下次我们还会再见!

我是黄啊码,码字的码,退。。。退。。。退。。。朝! 

未经允许不得转载:木盒主机 » 【黄啊码】垃圾回收可以赚钱,那php的垃圾回收机制你懂多少?

赞 (0)

相关推荐

    暂无内容!