PHP垃圾回收说到底是对变量及其所关联内存对象的操作,

  所以在讨论PHP的垃圾回收机制之前,先简要介绍PHP中变量及其内存对象的内部表示(其C源代码中的表示)。

  PHP官方文档中将PHP中的变量划分为两类:标量类型和复杂类型。

    标量类型包括布尔型、整型、浮点型和字符串;

    复杂类型包括数组、对象和资源;

    还有一个NULL比较特殊,它不划分为任何类型,而是单独成为一类。

PHP5.2中使用的内存回收算法是大名鼎鼎的Reference Counting,

    这个算法中文翻译叫做“引用计数”,其思想非常直观和简洁:

    为每个内存对象分配一个计数器,当一个内存对象建立时计数器初始化为1(因此此时总是有一个变量引用此对象),

    以后每有一个新变量引用此内存对象,则计数器加1,而每当减少一个引用此内存对象的变量则计数器减1,

    当垃圾回收机制运作的时候,将所有计数器为0的内存对象销毁并回收其占用的内存。

    而PHP中内存对象就是zval,而计数器就是refcount__gc。

    “引用计数”存在问题,就是当两个或多个对象互相引用形成环状后,

    内存对象的计数器则不会消减为0;

    这时候,这一组内存对象已经没用了,但是不能回收,从而导致内存泄露;

php5.3开始,使用了新的垃圾回收机制,

    首先PHP会分配一个固定大小的“根缓冲区”,

    这个缓冲区用于存放固定数量的zval,

    这个数量默认是10,000,

    如果需要修改则需要修改源代码Zend/zend_gc.c中的常量GC_ROOT_BUFFER_MAX_ENTRIES然后重新编译。

    由上文我们可以知道,

    一个zval如果有引用,要么被全局符号表中的符号引用,要么被其它表示复杂类型的zval中的符号引用。

    因此在zval中存在一些可能根(root)。

    这里我们暂且不讨论PHP是如何发现这些可能根的,这是个很复杂的问题,

    总之PHP有办法发现这些可能根zval并将它们投入根缓冲区。

    当根缓冲区满额时,PHP就会执行垃圾回收,此回收算法如下:

    1、对每个根缓冲区中的根zval按照深度优先遍历算法遍历所有能遍历到的zval,

      并将每个zval的refcount减1,同时为了避免对同一zval多次减1

      (因为可能不同的根能遍历到同一个zval),每次对某个zval减1后就对其标记为“已减”。

    2、再次对每个缓冲区中的根zval深度优先遍历,

      如果某个zval的refcount不为0,则对其加1,否则保持其为0。

    3、清空根缓冲区中的所有根(注意是把这些zval从缓冲区中清除而不是销毁它们),

      然后销毁所有refcount为0的zval,并收回其内存。

如果不能完全理解也没有关系,只需记住PHP5.3的垃圾回收算法有以下几点特性:

  1、并不是每次refcount减少时都进入回收周期,只有根缓冲区满额后在开始垃圾回收。

  2、可以解决循环引用问题。

  3、可以总将内存泄露保持在一个阈值以下。

与垃圾回收算法相关的PHP配置

  可以通过修改php.ini中的zend.enable_gc来打开或关闭PHP的垃圾回收机制,

  也可以通过调用gc_enable()或gc_disable()打开或关闭PHP的垃圾回收机制。

  在PHP5.3中即使关闭了垃圾回收机制,PHP仍然会记录可能根到根缓冲区,

  只是当根缓冲区满额时,PHP不会自动运行垃圾回收,

  当然,任何时候您都可以通过手工调用gc_collect_cycles()函数强制执行内存回收。

原文链接http://www.cnblogs.com/leoo2sk/archive/2011/02/27/php-gc.html

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

  1. .net垃圾回收机制编程调试试验

    1. 什么是CLR GC? 它是一个基于引用跟踪和代的垃圾回收器. 从本质上,它为系统中所有活跃对象都实现了一种引用跟踪模式,如果一个对象没有任何引用指向它,那么这个对象就被认为是垃圾对象,并且可以被 ...

  2. JavaScript具有自动垃圾回收机制

    JavaScript具有自动垃圾回收机制 原理: 找出那些不再继续使用的变量,然后释放其占用的内存.   正常的生命周期:     局部变量指在函数执行的过程中存在.而在这个过程中,会为局部变量在栈或 ...

  3. java垃圾回收机制

    1 .垃圾回收机制(GC)垃圾回收就是回收内存中不再使用对象:(1)垃圾回收的步骤:1)查找内存中不再使用的对象:2)释放这些对象所占用的内存:(2)查找内存中不再使用的对象方法:1)引用计数法如果一 ...

  4. 垃圾回收机制GC知识再总结兼谈如何用好GC

    一.为什么需要GC 应用程序对资源操作,通常简单分为以下几个步骤: 1.为对应的资源分配内存 2.初始化内存 3.使用资源 4.清理资源 5.释放内存 应用程序对资源(内存使用)管理的方式,常见的一般 ...

  5. 【转载】Java垃圾回收机制

    原文地址:http://www.importnew.com/19085.html Java垃圾回收机制 说到垃圾回收(Garbage Collection,GC),很多人就会自然而然地把它和Java联 ...

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

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

  7. JAVA的垃圾回收机制

    1. 垃圾回收的意义 在C++中,对象所占的内存在程序结束运行之前一直被占用,在明确释放之前不能分配给其它对象:而在Java中,当没有对象引用指向原先分配给某个对象的内存时,该内存便成为垃圾.JVM的 ...

  8. Python的垃圾回收机制

    Python的GC模块主要运用了“引用计数”(reference counting)来跟踪和回收垃圾.在引用计数的基础上,还可以通过“标记-清除”(mark and sweep)解决容器对象可能产生的 ...

  9. python垃圾回收机制的一些理解

    概览:       主要通过 引用计数来进行垃圾收集, 就是说,当一个对象没有被其他对象引用的时候,会释放掉内存.     但是会有一些循环引用的对象,通过上面的方法,是没有办法清除掉的.所以,pyt ...

  10. 闭包内的微观世界和js垃圾回收机制

    一.什么是闭包? 官方”的解释是:闭包是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分.相信很少有人能直接看懂这句话,因为他描述的太学术.其实这句话 ...

随机推荐

  1. NIS 报错No such map passwd.byname. Reason: Can't bind to server which serves this domain

    在NIS—client端使用命令:ypcat passwd ,把错如上题, 原因:client端ypbind服务未启动解决方法:当然是启动ypbind了,命令:service ypbind start ...

  2. ios 中清除webView的缓存

    在UIWebView下,可以使用 [[NSURLCache sharedURLCache] removeAllCachedResponses];//清除缓存 来实现清除缓存,但当替换使用WKWebVi ...

  3. 关于Cookie和Session的优缺点

    关于Cookie和Session的优缺点 具体来说cookie机制采用的是在客户端保持状态的方案,而session机制采用的是在服务器端保持状态的方案. Cookie的优缺点:优点:极高的扩展性和可用 ...

  4. ShareSdk使用心得

    1. 微信和朋友圈:分享的时候设置了链接和图片,但就是不显示: 需要指明ShareType为WEB_PAGE 2. 需要完整添加 ShareSdk 的所需要的权限,不然分享闪退,并且不报异常:网络请求 ...

  5. 51nod1069(nim博弈)

    题目链接: http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1069 题意: 中文题诶~ 思路: 一开始我以为需要把上一堆到 ...

  6. OID View

    http://oid-info.com/get/1.3.6.1.2.1.17.1.4.1.2

  7. ASP.NET Web API 全局权限和全局异常处理

    在开发中,我使用json格式序列化,所以将默认的xml序列化移除 public static class WebApiConfig { public static void Register(Http ...

  8. x86架构的android手机兼容性问题

    x86架构的android手机兼容性问题 http://www.cnblogs.com/guoxiaoqian/p/3984934.html 自从CES2012上Intel发布了针对移动市场的Medf ...

  9. Task使用小结

    Task是.NET推出数据任务处理的工作类,Task的使用也被越来越多的人讲解,这里仅仅介绍Task的部分使用介绍: 1.Task简单创建 --无返回值 Task.Factory.StartNew(( ...

  10. Solr入门之(8)中文分词器配置

    Solr中虽然提供了一个中文分词器,但是效果很差,可以使用IKAnalyzer或Mmseg4j 或其他中文分词器. 一.IKAnalyzer分词器配置: 1.下载IKAnalyzer(IKAnalyz ...