PHP7垃圾回收机制的案例分析

  介绍

这篇文章将为大家详细讲解有关PHP7垃圾回收机制的案例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。


简称GC。顾名思义,就是废物重利用的意思。
说垃圾回收机制之前,先接触一下内存泄漏。

内存泄漏:

某大神重口味充满画面感的形象解释:

大概意思就是申请了一块地儿拉了会儿屎,拉完后不收拾,那么那块儿地就算是糟蹋了,地越用越少,最后一地全是屎。说到底一句,用了记得还。一定程度上说,垃圾回收机制就是用来擦屁股的。

c语言垃圾回收机制:

如果用过c语言,那么申请内存的方式是malloc或者是calloc,然后你用完这个内存后,一定不要忘了用自由函数去释放掉,这就是手动垃圾回收,一般都是大神用这种方式。

php的自动垃圾回收机制是怎样的呢?

这个问题我们先这么想,我们都知道php是c语言实现的。你想想如何用c语言实现对一个变量的统计以及释放c语言是如何实现一个变量,从声明开始到最后没人用了,就把这个变量所占的内存给释放掉(<强>被垃圾回收)。

php进行内存管理的核心算法一共两项:
一是引用计数,二是写时拷贝

<>强声明一个php变量的时候强,c语言就在底层生成一个叫做zval的结构(结构体),如下:

 zval {
  字符串“a"//变量的名字是a
  价值zend_value//变量的值,联合体
  字符串类型//变量是字符串类型
  }

zval struct结构体

(1)保存php美元的变量名
(2) php美元的变量类型
(3) php变量一个美元的zend_value联合体

如果给<强>变量赋值强了,比如“hello world”,那么C语言就在底层再生成一个叫做zend_value的联盟(联合体)

 zend_value {
  字符串“hello world"//值的内容
  refcount 1//引用计数
  }

zend_value的联盟(联合体)

(1)保存php美元的变量的值hello world
(2)记录php美元变量引用次数

看到zval struct结构体和zend_value,如果面试官问你php变量为什么能够保存字符串“123”,也能保存数123字,你知道该怎么回答了吧?就答出重点zval中有该变量的类型,当是字符串123的时候,就类型是字符串,此指时价值向“123”;当是整数123的时候,zval的类型为int,值为123。

何为引用计数?

代码实战解析php变量引用计数

 $=& # 39;你好,& # 39;;
  回声xdebug_debug_zval(& # 39;一个# 39;);//refcount=1
  b=一美元;
  回声xdebug_debug_zval(& # 39;一个# 39;);//$ b引用一美元,故变量,refcount=2
  c=一美元;
  回声xdebug_debug_zval(& # 39;一个# 39;);//$ c引用一美元,故变量,refcount=3
  设置($ c);
  回声xdebug_debug_zval(& # 39;一个# 39;);//删除了$ c的引用,故变量,refcount=2 

运行结果:

:
(refcount=1, is_ref=0)字符串& # 39;你好,& # 39;(长度=11)
:
(refcount=2, is_ref=0)字符串& # 39;你好,& # 39;(长度=11)
:
(refcount=3, is_ref=0)字符串& # 39;你好,& # 39;(长度=11)
:
(refcount=2, is_ref=0)字符串& # 39;你好,& # 39;(长度=11)

何为拷贝复制?

 $=& # 39;你好# 39;;
  b=一美元;美元//赋值给$ b的时候,美元一个的值并没有真的复制了一份
  回声xdebug_debug_zval(& # 39;一个# 39;);//美元的引用计数为2
  $=& # 39;& # 39;;//当我们修改美元一个的值为123的时候,这个时候就不得已进行复制,避免$ b的值和一个美元的一样
  回声xdebug_debug_zval(& # 39;一个# 39;);///美元的引用计数为1 

运行结果:

:
(refcount=2, is_ref=0)字符串& # 39;你好# 39;(长度=5)
:
(refcount=1, is_ref=0)字符串& # 39;& # 39;(长度=5)

其实,当你把一个美元赋值给$ b的时候,美元一个的值并没有真的复制了一份,这样是对内存的极度不尊重,也是对时间复杂度的极度不尊重,计算机仅仅是将b指美元向了一美元的值而已,这就叫多快好省,那么,什么时候真正的发生复制呢?就是当我们修改美元一个的值为123的时候,这个时候就不得已进行复制,避免$ b的值和一个美元的一样。

通过简单的案例解释清楚了两个要点:引用计数和写时拷贝。

垃圾回收机制:

当一个zval在被扰乱的时候,或者从一个函数中运行完毕出来(就是局部变量)的时候等等很多地方,都会产生zval与zend_value发生断开的行为,这个时候zend引擎需要检测的就是zend_value的refcount是否为0,如果为0,则直接KO自由空出内容来。如果zend_value的重新计票不为0,这个价值不能被释放,但是也不代表这个zend_value是清白的,因为此zend_value依然可能是个垃圾。

PHP7垃圾回收机制的案例分析