什么是垃圾回收机制

使用的是“引用计数”方式进行回收。简单地理解的话,就是每个分配的内存区域都有一个计数器,记录有多少个变量指针指向这片内存。当指向该片内存的指针数量为0,那么该片内存区域就可以被回收。

什么又算垃圾

首先我们需要定义一下“垃圾”的概念, 说简单点是指变量的容器zval还存在,但是又没有任何变量名指向此zval。因此判断是否为垃圾的一个重要标准是有没有变量名指向变量容器zval。。

假设我们有一段PHP代码,使用了一个临时变量$tmp存储了一个字符串,在处理完字符串之后,就不需要这个$tmp变量了,$tmp变量对于我们来说可以算是一个“垃圾”了,但是$tmp其实并不是一个垃圾,

$tmp变量对我们没有意义,但是这个变量实际还存在,$tmp符号依然指向它所对应的zval,PHP代码中可能还会使用到此变量,所以不会将其定义为垃圾。

那么如果我们在PHP代码中使用完$tmp后,调用unset删除这个变量,那么$tmp是不是就成为一个垃圾了呢?先不着急回答这个问题。我们来举个例子:

  1. <?php
  2. $a = array('one');
  3. $a[] = &$a;
  4. unset($a);
  5. ?>

这样$a数组就有两个元素,一个索引为0,值为字符one,另外一个索引为1,为$a自身的引用,内部存储如下:

  1. a: (refcount=, is_ref=)=array (
  2. => (refcount=, is_ref=)='one',
  3. => (refcount=, is_ref=)=…
  4. )

“…”表示1指向a自身,是一个环形引用:

最后我们对$a进行unset,那么$a会从符号表中删除,同时$a指向的zval的refcount减少1

那么问题也就产生了,$a已经不在符号表中了,用户无法再访问此变量,但是$a之前指向的zval的refcount变为1而不是0,因此不能被回收,这样产生了内存泄露:

这样,这么一个zval就成为了一个真是意义的垃圾了,新的GC要做的工作就是清理这种垃圾。

为解决这种垃圾,产生了新的GC

    在PHP5.3版本中,使用了专门GC机制清理垃圾,在之前的版本中是没有专门的GC,那么垃圾产生的时候,没有办法清理,内存就白白浪费掉了。在PHP5.3源代码中多了以下文件:{PHPSRC}/Zend/zend_gc.h {PHPSRC}/Zend/zend_gc.c, 这里就是新的GC的实现,我们先简单的介绍一下算法思路,然后再从源码的角度详细介绍引擎中如何实现这个算法的。

新的GC算法

    在较新的PHP手册中有简单的介绍新的GC使用的垃圾清理算法,这个算法名为 Concurrent Cycle Collection in Reference Counted Systems , 这里不详细介绍此算法,根据手册中的内容来先简单的介绍一下思路:

首先我们有几个基本的准则:

1:如果一个zval的refcount增加,那么此zval还在使用,不属于垃圾

2:如果一个zval的refcount减少到0, 那么zval可以被释放掉,不属于垃圾

3:如果一个zval的refcount减少之后大于0,那么此zval还不能被释放,此zval可能成为一个垃圾

只有在准则3下,GC才会把zval收集起来,然后通过新的算法来判断此zval是否为垃圾。那么如何判断这么一个变量是否为真正的垃圾呢?

简单的说,就是对此zval中的每个元素进行一次refcount减1操作,操作完成之后,如果zval的refcount=0,那么这个zval就是一个垃圾。

PHP5.3针对这个重大的缺陷做了优化。虽然其基础仍然是引用计数,但是在做了一些改良,能够将环状引用导致的内存泄露控制在一定的规模以内。当然,这并不是说你可以随便滥用内存,编写代码时仍然要小心为上!
补充重点:
1.PHP脚本运行完毕,该脚本申请的所有内存空间都会释放,不管是否存在环状引用。因此环状引用内存泄露的问题一般只影响长时间运行的程序脚本。
 
2.垃圾回收机制需要满足一定的条件才会执行。因此unset后,系统并不一定会立即回收垃圾。
 
3.unset的作用。
“unset只是断开一个变量到一块内存区域的连接,同时将该内存区域的引用计数-1”。也就是说,如果有一个以上的变量指向同一个内存区域,或者存在环状引用,那么unset不会使内存区域释放。断开也说明unset并不会直接删除内存区域,而只是改变其引用计数而已。
 
4.$a=null的作用。
“$a = null 是直接将$a 指向的数据结构置空,同时将其引用计数归0”。根据我对这个定义的理解,=null操作可以立即释放掉内存空间!

因此很多PHP技巧中不厌其烦地对我们说,先将变量设为null,再unset。理解其深层原理后,我才彻底理解了这样做的原因!=null才是根本!

理解PHP的垃圾回收机制的更多相关文章

  1. 理解Android Java垃圾回收机制

    Jvm(Java虚拟机)内存模型 从Jvm内存模型中入手对于理解GC会有很大的帮助,不过这里只需要了解一个大概,说多了反而混淆视线. Jvm(Java虚拟机)主要管理两种类型内存:堆和非堆.堆是运行时 ...

  2. 03 JVM的垃圾回收机制

    1.前言 理解JVM的垃圾回收机制(简称GC)有什么好处呢?作为一名软件开发者,满足自己的好奇心将是一个很好的理由,不过更重要的是,理解GC工作机制可以帮助你写出更好的Java程序. 在学习GC前,你 ...

  3. Android内存优化3 了解java GC 垃圾回收机制1

    开篇废话 如果我们想要进行内存优化的工作,还是需要了解一下,但这一块的知识属于纯理论的,有可能看起来会有点枯燥,我尽量把这一篇的内容按照一定的逻辑来走一遍.首先,我们为什么要学习垃圾回收的机制,我大概 ...

  4. JVM虚拟机—JVM的垃圾回收机制(转载)

    1.前言 理解JVM的垃圾回收机制(简称GC)有什么好处呢?作为一名软件开发者,满足自己的好奇心将是一个很好的理由,不过更重要的是,理解GC工作机制可以帮助你写出更好的Java程序. 在学习GC前,你 ...

  5. Android性能调优篇之探索垃圾回收机制

    开篇废话 如果我们想要进行内存优化的工作,还是需要了解一下,但这一块的知识属于纯理论的,有可能看起来会有点枯燥,我尽量把这一篇的内容按照一定的逻辑来走一遍.首先,我们为什么要学习垃圾回收的机制,我大概 ...

  6. 【转】深入理解 Java 垃圾回收机制

    深入理解 Java 垃圾回收机制   一.垃圾回收机制的意义 Java语言中一个显著的特点就是引入了垃圾回收机制,使c++程序员最头疼的内存管理的问题迎刃而解,它使得Java程序员在编写程序的时候不再 ...

  7. 深入理解java垃圾回收机制

    深入理解java垃圾回收机制---- 一.垃圾回收机制的意义 Java语言中一个显著的特点就是引入了垃圾回收机制,使c++程序员最头疼的内存管理的问题迎刃而解,它使得Java程序员在编写程序的时候不再 ...

  8. PHP垃圾回收机制理解

    使用的是"引用计数"方式进行回收.简单地理解的话,就是每个分配的内存区域都有一个计数器,记录有多少个变量指针指向这片内存.当指向该片内存的指针数量为0,那么该片内存区域就可以被回收 ...

  9. 深入理解 Java 垃圾回收机制

            深入理解 Java 垃圾回收机制 一:垃圾回收机制的意义 java  语言中一个显著的特点就是引入了java回收机制,是c++程序员最头疼的内存管理的问题迎刃而解,它使得java程序员 ...

随机推荐

  1. ubuntu解压时中文出现乱码

    一.乱码类似这样的:╫╩┴╧╖┤╤▌▓т╒╛╦┘╢╚│ 今天遇到需要上传十几G的图片,在wins上压缩成zip格式,在上传到服务器上,结果出现乱码.然后各种百度心塞. 最初查到原因: 这个主要是因为z ...

  2. Docker的基本概念

    Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化.容器是完全使用沙箱机制,相互之间不会有任何 ...

  3. Parallel线程安全问题

    废话不多说,上代码: using System; using System.Collections.Generic; using System.Threading.Tasks; namespace P ...

  4. Web安全之XSS Platform搭建及使用实践

    Web安全之XSS Platform搭建及使用实践 一.背景 XSS Platform 是一个非常经典的XSS渗透测试管理系统,原作者在2011年所开发,由于后来长时间没有人维护,导致目前在PHP7环 ...

  5. 吴恩达机器学习笔记57-基于内容的推荐系统(Content Based Recommendations)

    假使我们是一个电影供应商,我们有 5 部电影和 4 个用户,我们要求用户为电影打分. 前三部电影是爱情片,后两部则是动作片,我们可以看出Alice 和Bob 似乎更倾向与爱情片, 而 Carol 和 ...

  6. [Swift]LeetCode421. 数组中两个数的最大异或值 | Maximum XOR of Two Numbers in an Array

    Given a non-empty array of numbers, a0, a1, a2, … , an-1, where 0 ≤ ai < 231. Find the maximum re ...

  7. Docker for windows : 安装linux

    一.Linux 1.拉取镜像 docker pull hub.c..com/library/oraclelinux:latest 2.创建linux容器 C:\Users\K-Jso>docke ...

  8. SpringBoot时间戳与MySql数据库记录相差14小时排错

    项目中遇到存储的时间戳与真实时间相差14小时的现象,以下为解决步骤. 问题 CREATE TABLE `incident` ( `id` int(11) NOT NULL AUTO_INCREMENT ...

  9. java 网络通信传输层协议——UDP和TCP

    本文原文由作者“zskingking”发表于:jianshu.com/p/271b1c57bb0b,本次收录有改动. 1.点评 互联网发展至今已经高度发达,而对于互联网应用(尤其即时通讯网专注的即时通 ...

  10. 并发编程(二)—— CountDownLatch、CyclicBarrier和Semaphore

    本文将讲解CountDownLatch,CyclicBarrier和Semaphore这三个并发包里面的辅助类. CountDownLatch 正如每个Java文档所描述的那样,CountDownLa ...