前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >php 的垃圾回收策略

php 的垃圾回收策略

作者头像
用户3147702
发布2022-06-27 12:56:59
3840
发布2022-06-27 12:56:59
举报
文章被收录于专栏:小脑斧科技博客

1. 概述

此前我们了解过 java 和 python 如何管理内存以及运行过程中的垃圾收集。 python 的内存管理与垃圾收集 java 的存活判定与垃圾收集

本篇日志我们来介绍博主另一个比较熟悉的语言 — php 的内存管理方式以及垃圾回收机制。

2. php 变量存储结构

所有的 php 类型在 php 内部都是用一个 zval 结构存储的,下面是 zval 的存储结构 _zval_struct:

代码语言:javascript
复制
typedef union _zvalue_value {  
    long lval;                  /* long value */ 
    double dval;                /* double value */ 
    struct {  
        char *val;  
        int len;  
    } str;  
    HashTable *ht;              /* hash table value */ 
    zend_object_value obj;  
} zvalue_value;  

struct _zval_struct {  
    zvalue_value value;       
    zend_uint refcount__gc;  
    zend_uchar type;    /* active type */ 
    zend_uchar is_ref__gc;  
};

其中联合体“_zvalue_value”用于表示PHP中所有变量的值,这里之所以使用union,是因为一个zval在一个时刻只能表示一种类型的变量。 可以看到,_zval_struct 中除了 zvalue_value 类型的变量值和 zend_uchar 类型的变量类型数据以外,还存储了 refcount__gc 和 is_ref__gc 两个字段。 1. is_ref — is_ref 是一个 bool 类型的值,他用来标识该变量是否属于引用集合(reference set) 2. refcount — 引用计数器

2.1. 查看变量完整信息

通过 xdebug_debug_zval 函数可以查看变量的完整信息:

代码语言:javascript
复制
<?php
$a = "new string";
xdebug_debug_zval('a');
?>

打印出了:
a: (refcount=1, is_ref=0)='new string'

3. 引用计数法与循环引用问题

与 python 一样,php 也是通过引用计数法来实现内存的回收的,变量中的 refcount 字段就是为了实现这一目的存在的。 当一个对象的引用计数变为 0 时, 它被垃圾回收。 当然,与 python 已经其他使用引用计数法作为垃圾回收机制的语言一样,PHP 的垃圾回收机制也存在循环引用问题。

下面的例子说明了这一情况:

代码语言:javascript
复制
<?php
$a = array( 'one' );
$a[] =& $a;
xdebug_debug_zval( 'a' );
?>

程序输出了: a: (refcount=2, is_ref=1)=array ( 0 => (refcount=1, is_ref=0)=’one’, 1 => (refcount=2, is_ref=1)=… )

在 php 执行过程中,循环引用的变量的引用计数永远不可能减到0,也就永远不会被引用计数规则的垃圾回收器回收,这样就造成了内存泄漏。

4. 回收周期(Collecting Cycles)

PHP5.3.0 实现了回收周期算法,从而处理了因为循环引用造成的内存泄漏问题。 可以通过在配置文件中指定 zend.enable_gc 来修改是否进行该算法的垃圾回收。

这个算法的主要步骤如下: 1. 算法建立了一个根缓冲区,所有的 zval 变量容器都存放在根缓冲区中,如下图紫色部分 2. 当缓冲区满时,垃圾回收器遍历整个根缓冲区,将所有根缓冲区中的变量全部模拟删除 3. 模拟恢复每个已经被模拟删除的变量,原则是只恢复模拟删除后引用计数大于 0 的变量 4. 清除所有在模拟恢复步骤中没有被恢复的变量

由于在对象全部被模拟删除,循环引用的对象的引用计数会相应减少到 0,从而解决了循环引用造成的内存泄漏问题。

5. 参考资料

http://php.net/manual/zh/features.gc.php。 https://researcher.watson.ibm.com/researcher/files/us-bacon/Bacon01Concurrent.pdf。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2018-10-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 小脑斧科技博客 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 概述
  • 2. php 变量存储结构
    • 2.1. 查看变量完整信息
    • 3. 引用计数法与循环引用问题
    • 4. 回收周期(Collecting Cycles)
    • 5. 参考资料
    相关产品与服务
    对象存储
    对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档