资讯专栏INFORMATION COLUMN

PHP垃圾回收机制

luck / 1801人阅读

摘要:在中算法,当节点缓冲区满了之后,垃圾分析算法就会启动,并且会释放掉发现的垃圾,从而回收内存。在编程中程序员不需要手动处理内存资源分配与释放,意味着本身实现了垃圾回收处理机制。

PHP是一种弱类型的脚本语言,弱类型不表示PHP变量没有类型的区别,PHP变量有8种原始类型:
四种标量类型:

boolean(布尔值)

integer(整型)

float(浮点型)

两种复合类型:

array(数组)

object(对象)

两种特殊类型:

resource(资源)

NULL


在引擎内部,变量都是用一个结构体来表示的。这个结构体可以在{PHPSRC}/Zend/zend.h中找到:

  struct _zval_struct {  
       /* Variable information */  
       zvalue_value value;     /* value */  
       zend_uint refcount__gc;  //代表一个计数器,表示有多少个变量名指向这个zval容器
       zend_uchar type;    /* active type */  
       zend_uchar is_ref__gc;  //此字段是一个布尔值,用来标识变量是否是一个引用,通过这个字段,PHP引擎可以区分一般变量和引用变量
   };  
copy on write(写时复制技术)
父进程fork子进程之后,子进程的地址空间还是简单的指向父进程的地址空间,只有当子进程需要写地址空间中的内容的时候,才会多带带分离一份给子进程,这样就算子进程马上调用exec函数也没有关系,因为根本就不需要从父进程的地址空间中拷贝内容,这样就节省了内存同时又提高了速度。

这个逻辑可以叙述为:对一个一般变量a(isref=0)进行一般的赋值操作,如果a所指向的zval的计数refcount大于1,那么需要为a重新分配一个新的zval,并且把之前的zval的计数refcount减少1。

PHP5.3版本中对于新的GC算法(Concurrent Cycle Collection in Reference Counted Systems)

几个基本准则:

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

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

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

新的GC算法目的就是防止循环引用的变量引起内存泄露问题。在PHP中GC算法,当节点缓冲区满了之后,垃圾分析算法就会启动,并且会释放掉发现的垃圾,从而回收内存。

现在,如果我们试一下,将数组的引用赋值给数组中的一个元素,有意思的事情发生了:

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

a: (refcount=2, is_ref=1)=array (
   0 => (refcount=1, is_ref=0)="one",
   1 => (refcount=2, is_ref=1)=...
)

“...”表示1指向a自身,是一个环形引用(循环引用):

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

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

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

在PHP编程中程序员不需要手动处理内存资源分配与释放,意味着PHP本身实现了垃圾回收处理机制。
PHP5.2中的垃圾回收算法---Reference Counting
这个算法叫做“引用计数”,其思想非常直观和简洁:为每个内存对象分配一个计数器,当一个内存对象建立时计数器初始化为1(因此此时总是有一个变量引用此对象),以后每有一个新变量引用此内存对象,则计数器加1,而每当减少一个引用此内存对象的变量则计数器减1,当垃圾回收机制运作时,将所有计数器为0的内存对象销毁并回收其占用的内存。而php中内存对象就是zval,而计数器就是refcount__gc。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/28431.html

相关文章

  • PHP回收周期

    摘要:原文回收周期,增加一篇论文在底部。就是说,仅仅在引用计数减少到非零值时,才会产生垃圾周期。如果他们是循环引用周期的一部分,将永不能被清除进而导致内存泄漏。这个函数将返回使用这个算法回收的周期数。引用计数系统中的同步周期回收 原文:回收周期(Collecting Cycles) ,增加一篇论文在底部。 以下过程仅对数组和对象类型起作用。 传统上,像以前的 php 用到的引用计数内存机制,...

    Astrian 评论0 收藏0
  • php底层原理之垃圾回收机制

    摘要:总结垃圾回收机制以的引用计数机制为基础以前只有该机制同时使用根缓冲区机制,当发现有存在循环引用的时,就会把其投入到根缓冲区,当根缓冲区达到配置文件中的指定数量后,就会进行垃圾回收,以此解决循环引用导致的内存泄漏问题开始引入该机制 php垃圾回收机制,对于PHPer来说是一个不陌生但是又不是很熟悉的内容。那么php是怎么实现对不需要的内存进行回收的呢? php变量的内部存储结构 首先还是...

    light 评论0 收藏0
  • 【转】浅谈PHP5中垃圾回收算法(Garbage Collection)的演化

    摘要:所有这些类型,在内部统一用一个叫做的结构表示,在源代码中这个结构名称为。的具体定义在源代码的文件中,下面是相关代码的摘录。 【转】浅谈PHP5中垃圾回收算法(Garbage Collection)的演化 前言 PHP是一门托管型语言,在PHP编程中程序员不需要手工处理内存资源的分配与释放(使用C编写PHP或Zend扩展除外),这就意味着PHP本身实现了垃圾回收机制(Garbage C...

    AdolphLWQ 评论0 收藏0
  • 带你入门 JavaScript ES6 (五) 集合

    摘要:一概述集合是引入的新的内置对象类型,其特点同数学意义的集合,即集合内所有元素不重复元素唯一。数组集合对比数组和集合,数组可以加入重复数据,而集合的所有元素是唯一的不允许重复。因此,适合临时存放一组对象,以及存放跟对象绑定的信息。 本文同步带你入门 带你入门 JavaScript ES6 (五) 集合,转载请注明出处。 前面我们学习了: for of 变量和扩展语法 块作用域变量和解构...

    BetaRabbit 评论0 收藏0
  • PHP垃圾回收机制-引用计数基本知识(5.3)

    摘要:后者的例子在给巨大的一个知名的组件库的模板组件做单元测试时,就可能会出现问题。 PHP的垃圾回收机制 垃圾回收器,全称Garbage Collection,简称GC,5.3版本之前 只是简单判断变量的zval的refcount是否为0,是的话就释放,不是直至进程结束(隐藏着变量内存溢出的风险). 如果你已经安装了» Xdebug,你能通过调用函数 xdebug_debug_zval()...

    dreambei 评论0 收藏0

发表评论

0条评论

luck

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<