`
student_lp
  • 浏览: 437995 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

php垃圾回收之回收策略和算法

阅读更多

一、垃圾回收实现方式

     在以前的php中用到的是引用计数机制处理垃圾回收问题,但是这个机制存在一个弊端,就是无法处理循环引用引起的内存泄露。然而在php5.3.0以后的版本中(包含5.3.0)使用了专门GC机制(同步算法)清理垃圾,来处理这个内存泄露问题。下面就是介绍它是如何实现的:

    首先要了解几个基本的准则:

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就是一个垃圾。这个原理咋看起来很简单,但是又不是那么容易理解,下面通过结构图来深入理解:


     A:为了避免每次变量的refcount减少的时候都调用GC的算法进行垃圾判断,此算法会先把所有前面准则3情况下的zval节点放入一个节点(root)缓冲区(root buffer),并且将这些zval节点标记成紫色,同时算法必须确保每一个zval节点在缓冲区中之出现一次。当缓冲区被节点塞满的时候,GC才开始开始对缓冲区中的zval节点进行垃圾判断。

     B:当缓冲区满了之后,算法以深度优先对每一个节点所包含的zval进行减1操作,为了确保不会对同一个zval的refcount重复执行减1操作,一旦zval的refcount减1之后会将zval标记成灰色。需要强调的是,这个步骤中,起初节点zval本身不做减1操作,但是如果节点zval中包含的zval又指向了节点zval(环形引用),那么这个时候需要对节点zval进行减1操作。

     C:算法再次以深度优先判断每一个节点包含的zval的值,如果zval的refcount等于0,那么将其标记成白色(代表垃圾),如果zval的refcount大于0,那么将对此zval以及其包含的zval进行refcount加1操作,这个是对非垃圾的还原操作,同时将这些zval的颜色变成黑色(zval的默认颜色属性)

     D:遍历zval节点,将C中标记成白色的节点zval释放掉。

二、举例详解垃圾回收过程

     通过上面的说明,大家可能已经有了一定的印象,那实际应用中是如何具体操作的呢?下面就通过例子说明:

    ①在刚刚声明变量并赋值的情况下,其实就相当于准则1(如果一个zval的refcount增加,那么此zval还在使用,不属于垃圾),变量不是垃圾,也不会进行gc检查。

$a = "one";
$b = array();
$b[] = $a;
$b[] = & $b;
$c = "two";
//声明了三个变量$a、$b、$c。这个时候refcount都是增加的情况,变量不是垃圾也不会放入到root缓冲器等待垃圾检查。
xdebug_debug_zval( 'a' );  
xdebug_debug_zval( 'b' );  
xdebug_debug_zval( 'c' );  
//输出分别如下:
a: (refcount=2, is_ref=0)='one'
b: (refcount=2, is_ref=1)=array (  
   0 => (refcount=2, is_ref=0)='one',  
   1 => (refcount=2, is_ref=1)=... 
)  
c: (refcount=1, is_ref=0)='two'

   ②在上面的基础上,我们调用了unset()函数释放变量b和c。如下:

unset($b);
unset($c);
xdebug_debug_zval( 'a' ); 
//输出如下:
a: (refcount=2, is_ref=0)='one'

     调用unset函数后,$b和$c对应容器中的refcount都会减1,但是他们的效果却不相同:先看$c调用unset($c)后,$c的refcount就编程了0,符合准则2,则$c对应的zval容器就是垃圾会被回收;再看$b调用unset($b)后,但是$b的第1个引用仍然指向$b所对应的zval容器,只不过$b对应的zval容器的refcount会减1,值会从2变成1。这时候容器的refcount虽然减1,但仍然不为零,则符合准则3,会把$b对应的zval,放入到root缓冲区中。等待gc垃圾校验操作,也就是进入到了(二)中的(A)情况。

     ③在往后的操作就是(二)中描述的了。经历(二)中的ABCD过程后,变量$b对应的zval容器会被释放,完成了垃圾回收,也解决了循环引用的内存泄露问题。

三、垃圾回收器配置使用

     在PHP中,GC默认是开启的,你可以通过ini文件中的 zend.enable_gc 项来开启或则关闭GC。当GC开启的时候,垃圾分析算法将在节点缓冲区(roots buffer)满了之后启动。缓冲区默认可以放10,000个值,当然你也可以通过修改Zend/zend_gc.c中的GC_ROOT_BUFFER_MAX_ENTRIES 来改变这个数值,需要重新编译链接PHP。当GC关闭的时候,垃圾分析算法就不会运行,但是相关节点还会被放入节点缓冲区,这个时候如果缓冲区节点已经放满,那么新的节点就不会被记录下来,这些没有被记录下来的节点就永远也不会被垃圾分析算法分析。如果这些节点中有循环引用,那么有可能产生内存泄漏。之所以在GC关闭的时候还要记录这些节点,是因为简单的记录这些节点比在每次产生节点的时候判断GC是否开启更快,另外GC是可以在脚本运行中开启的,所以记录下这些节点,在代码运行的某个时候如果又开启了GC,这些节点就能被分析算法分析。当然垃圾分析算法是一个比较耗时的操作。

    在PHP代码中我们可以通过gc_enable()和gc_disable()函数来开启和关闭GC,也可以通过调用gc_collect_cycles()在节点缓冲区未满的情况下强制执行垃圾分析算法。这样用户就可以在程序的某些部分关闭或则开启GC,也可强制进行垃圾分析算法。 

     

  • 大小: 29.9 KB
分享到:
评论

相关推荐

    php 垃圾回收算法原理, 英文版

    ### PHP垃圾回收算法原理 #### 引言 在软件开发领域,自动存储回收技术通过引用计数...随着处理器速度的持续提高和RAM容量的不断扩大,这种优化后的引用计数垃圾回收算法有望在未来获得更广泛的应用和发展。

    智慧废品回收系统-2.7.4.zip

    该系统通过智能化的设备和算法,实现了废品分类、回收、运输和处理的自动化和智能化。 系统的核心设备包括智能垃圾桶、智能回收箱和智能运输车。智能垃圾桶可以实现对废品的分类,包括可回收物、有害垃圾、厨余...

    Php引用计时器和垃圾回收机制.docx

    PHP作为一种动态类型的编程语言,其变量管理机制包括引用计数器和垃圾回收机制,这两者是PHP内存管理的核心。本文将深入探讨这两个概念,以及它们在PHP中的实现方式。 首先,让我们了解PHP变量的内部结构。PHP的...

    垃圾回收器是什么1

    垃圾回收器是编程语言中的一个重要概念,特别是在Java和Oracle的Hotspot及OpenJDK等...不同的JVM实现,如Hotspot和OpenJDK,以及不同的编程语言,可能有不同的垃圾回收策略和实现,需要根据具体场景进行选择和调整。

    Php引用计时器和垃圾回收机制.pdf

    在PHP5.3以后的版本,引入了一种更复杂的垃圾回收算法,称为“引用计数+可达性检测”,它结合了引用计数和追踪循环引用的方法,以更有效地回收内存。 在实际编程中,理解这些机制对于优化性能和避免内存泄漏至关...

    浅析PHP7 的垃圾回收机制

    具体到PHP7的垃圾回收实现,zend_refcounted_h是存储引用计数和垃圾回收信息的结构体。该结构体包括refcount字段,用于记录引用次数,以及gc_info字段,用于存储垃圾回收过程中的位置和颜色信息。在垃圾回收过程中,...

    深入解析PHP垃圾回收机制对内存泄露的处理

    新的垃圾回收算法通过标记和清扫的方式工作。PHP维护了一个根缓冲区(rootbuffer),其中存储了所有活动zval的节点信息。当rootbuffer满了或者通过手动调用gc函数时,垃圾回收函数会启动。在这个过程中,算法会从...

    PHP进阶学习之垃圾回收机制详解

    【PHP进阶学习之垃圾回收机制详解】 在深入探讨PHP的垃圾回收机制之前,首先要明白的是,垃圾回收(Garbage Collection, GC)是编程语言中用于自动管理内存的一种技术,它的目的是自动识别并释放不再使用的内存空间...

    掌握PHP垃圾回收机制详解

    PHP中的垃圾回收机制主要依赖于引用计数(Reference Counting)和写时复制(Copy-On-Write,简称COW)技术,这两个概念共同构成了PHP内存管理的一部分。 首先,我们需要理解什么是引用计数。在PHP中,每个变量都...

    二手回收网站带后台

    - 设置和调整推荐机和回收机的展示策略。 在开发这样一个二手回收网站时,需要考虑用户体验、数据安全、支付接口集成、SEO优化等多个方面。同时,后台系统的设计应具有可扩展性和稳定性,以应对不断增长的业务需求...

    PHP垃圾回收机制简单说明

    引用计数是一种简单的垃圾回收算法,它的工作原理是记录每一个值被引用的次数。引用计数机制包含以下几个关键点: 1. 当一个新的变量创建时,或者一个已存在的变量被赋予一个新的值时,将会在内存中分配一个空间,...

    PHP实例开发源码—2021最新百分百储值卡回收网站PHP完整源码.zip

    3. **价格计算与回收**:网站需要有计算回收价格的算法,这可能涉及到与市场价的比较或按固定比例计算。PHP可以用来编写这些逻辑。 4. **支付集成**:如果网站接受在线支付,源码中会包含与第三方支付平台(如...

    PHP程序员面试宝典1.zip

    这包括了解如何优化代码执行效率,如避免全局变量,使用恰当的数据结构,以及理解PHP的内存管理和垃圾回收机制。另外,了解如何使用缓存技术(如Memcached、Redis)提高网站性能也是必不可少的。 版本控制系统的...

    PHP程序员面试宝典 笔试 (PHP版).zip

    最后,了解并准备一些常见的面试问题,如“解释PHP的垃圾回收机制”、“描述一次你优化代码性能的经历”、“谈谈你对PHP7新特性的理解”等,将有助于你在面试中表现出色。 总之,《PHP程序员面试宝典 笔试 (PHP版)...

    php实现主存分配与回收

    这部分代码可能涉及到了数据结构和算法的设计,以及可能的前端图表库如ECharts或Highcharts的使用,以实现内存使用情况的图形化展示。 总的来说,这个项目提供了一个实战平台,让你可以深入学习和理解内存管理的...

    66道算法题目+php解题+java解题.zip

    Java是一种高性能、跨平台的面向...自动内存管理(垃圾回收): Java具有自动内存管理机制,通过垃圾回收器自动回收不再使用的对象,使得开发者不需要手动管理内存,减轻了程序员的负担,同时也减少了内存泄漏的风险。

    官方php源代码 php-7.4.5.tar.gz

    通过分析`php-7.4.5`的源码,我们可以了解其设计理念,学习如何实现高效的数据结构和算法,以及如何设计健壮的API接口。此外,源代码中丰富的注释也是宝贵的教育资源,帮助我们更好地理解PHP的内部工作原理。 总结...

    PHP source

    PHP使用了自己的内存管理机制,包括ZEND内存池和垃圾回收机制。ZEND内存池提供了一种高效分配和回收内存的方式,避免了频繁的系统调用。垃圾回收机制则自动回收不再使用的内存,防止内存泄漏。 四、PHP函数与类 ...

Global site tag (gtag.js) - Google Analytics