当前位置:Gxlcms > PHP教程 > PHP是如何做垃圾回收的(图文)

PHP是如何做垃圾回收的(图文)

时间:2021-07-01 10:21:17 帮助过:23人阅读

PHP是如何做垃圾回收的?

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

变量的实现

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

PHP 5.* zval 和 zend_value 结构

  1. struct _zval_struct { // 结构体
  2. zvalue_value value;
  3. zend_uint refcount__gc;
  4. zend_uchar type;
  5. zend_uchar is_ref__gc;
  6. }
  7. typedef union _zvalue_value { // 联合体
  8. long lval;
  9. double dval;
  10. struct {
  11. char *val;
  12. int len;
  13. } str; // 字符串
  14. HashTable *ht; // 数组
  15. zend_object_value obj; // 对象
  16. zend_ast *ast;
  17. } zvalue_value;

PHP 7.0 zval 和 zend_value 结构

  1. struct _zval_struct {
  2. union {
  3. zend_long lval; /* long value */
  4. double dval; /* double value */
  5. zend_refcounted *counted;
  6. zend_string *str;
  7. zend_array *arr;
  8. zend_object *obj;
  9. zend_resource *res;
  10. zend_reference *ref;
  11. zend_ast_ref *ast;
  12. zval *zv;
  13. void *ptr;
  14. zend_class_entry *ce;
  15. zend_function *func;
  16. struct {
  17. uint32_t w1;
  18. uint32_t w2;
  19. } ww;
  20. } value;
  21. union {
  22. struct {
  23. ZEND_ENDIAN_LOHI_4(
  24. zend_uchar type, /* active type */
  25. zend_uchar type_flags,
  26. zend_uchar const_flags,
  27. zend_uchar reserved) /* call info for EX(This) */
  28. } v;
  29. uint32_t type_info;
  30. } u1;
  31. union {
  32. uint32_t var_flags;
  33. uint32_t next; /* hash collision chain */
  34. uint32_t cache_slot; /* literal cache slot */
  35. uint32_t lineno; /* line number (for ast nodes) */
  36. uint32_t num_args; /* arguments number for EX(This) */
  37. uint32_t fe_pos; /* foreach position */
  38. uint32_t fe_iter_idx; /* foreach iterator index */
  39. } u2;
  40. };

PHP5 与 PHP7 引用计数的对比

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

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

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

垃圾回收.draw.io-PHP7

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

什么是垃圾

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

1. refcount 增加的不是

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

3. refcount 减少,并且不等于0的才是垃圾

垃圾收集

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

2. 没有在缓冲区中存在过

3. 没有被标记过

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

回收算法

论文:https://researcher.watson.ibm.com/researcher/files/us-bacon/Bacon01Concurrent.pdf

PHP 5.3 版本以及之后的版本

1. 将垃圾放到一个 root 池中

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

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

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

5. 对 refcount!=0 的 refcount+1

四色切换

以上就是PHP是如何做垃圾回收的(图文)的详细内容,更多请关注Gxlcms其它相关文章!

人气教程排行