php如何进行垃圾回收,PHP 是如何做垃圾回收的

PHP 是如何做垃圾回收的

包含 php 5 与 php7 的变量实现和垃圾回收的对比

变量的实现

PHP 的变量是弱类型的,可以表示整数、浮点数、字符串等类型。PHP 的变量是使用结构体 zval 表示的

PHP 5.* zval 和 zend_value 结构

struct _zval_struct { // 结构体

zvalue_value value;

zend_uint refcount__gc;

zend_uchar type;

zend_uchar is_ref__gc;

}

typedef union _zvalue_value { // 联合体

long lval;

double dval;

struct {

char *val;

int len;

} str; // 字符串

HashTable *ht; // 数组

zend_object_value obj; // 对象

zend_ast *ast;

} zvalue_value;

PHP 7.0 zval 和 zend_value 结构

struct _zval_struct {

union {

zend_long lval; /* long value */

double dval; /* double value */

zend_refcounted *counted;

zend_string *str;

zend_array *arr;

zend_object *obj;

zend_resource *res;

zend_reference *ref;

zend_ast_ref *ast;

zval *zv;

void *ptr;

zend_class_entry *ce;

zend_function *func;

struct {

uint32_t w1;

uint32_t w2;

} ww;

} value;

union {

struct {

ZEND_ENDIAN_LOHI_4(

zend_uchar type, /* active type */

zend_uchar type_flags,

zend_uchar const_flags,

zend_uchar reserved) /* call info for EX(This) */

} v;

uint32_t type_info;

} u1;

union {

uint32_t var_flags;

uint32_t next; /* hash collision chain */

uint32_t cache_slot; /* literal cache slot */

uint32_t lineno; /* line number (for ast nodes) */

uint32_t num_args; /* arguments number for EX(This) */

uint32_t fe_pos; /* foreach position */

uint32_t fe_iter_idx; /* foreach iterator index */

} u2;

};

PHP5 与 PHP7 引用计数的对比

php 5.* 变量赋值等操作引用计数如图所示,在倒数第二步,会形成一个循环引用,并且在 unset 操作之后,会产生垃圾。

a30d504442950c60635d17cd686d64a9.png

PHP 7 的计数放到了具体的 value 中,zval 不存在写时复制(写时分离)。

并且 PHP 7 的有一个专门的 zend_reference 用来表示引用。

7da1dee9d41a6c10fe53dbb491af338c.png

有了以上关于 PHP 变量存储的知识,我们可以理解一下 PHP 是如何做垃圾回收的了。

什么是垃圾

首先,我们需要定义什么是垃圾。

refcount 增加的不是

refcount 等于0的不是,这个会被直接清除

refcount 减少,并且不等于0的才可能是垃圾

垃圾收集

php7 要求数据类型是数组和对象,并且 type_flag 是 IS_TYPE_COLLECTABLE

没有在缓冲区中存在过

没有被标记过

标记为紫色,并且放到缓冲区中

回收算法

PHP 5.3 版本以及之后的版本

将垃圾放到一个 root 池中

当满 10000 个节点的时候进行垃圾回收

遍历双向链表中的节点 refcount-1

遍历双向链表将 refcount=0 的节点删除,到free队列中

对 refcount!=0 的 refcount+1

bb020691089ff91641a01d62d77f7fc0.png

原文出处:https://www.cnblogs.com/wudanyang/p/10844789.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值