0

0

浅谈PHP源码三十三:PHP5.3新增加的垃圾回收机制(Garbage Collection)基础

不言

不言

发布时间:2018-06-29 10:00:34

|

2025人浏览过

|

来源于php中文网

原创

这篇文章主要介绍了关于浅谈php源码三十三:php5.3新增加的垃圾回收机制(garbage collection)基础,有着一定的参考价值,现在分享给大家,有需要的朋友可以参考一下

浅谈PHP源码三十三:PHP5.3新增加的垃圾回收机制(Garbage Collection)基础
PHP5.3中新增加了垃圾回收机制,据说很先进,据说引诱了我去看看其先进的实现。
官方说明文档请猛击Garbage Collection
中文版地址:http://docs.php.net/manual/zh/features.gc.php
【垃圾回收机制的嵌入方式】
zend_gc.h文件在zend.h的749行被引用:#include “zend_gc.h”
从而替换覆盖了在237行引用的zend_alloc.h文件中的ALLOC_ZVAL等宏
zend/zend_gc.h文件的202行开始

 /* The following macroses override macroses from zend_alloc.h */#undef  ALLOC_ZVAL#define ALLOC_ZVAL(z) \
do {\
(z) = (zval*)emalloc(sizeof(zval_gc_info));\
GC_ZVAL_INIT(z);\
} while (0)

ALLOC_ZVAL宏在zend_alloc.h中的定义是分配一个zval结构的内存空间。新的ALLOC_ZVAL宏分配了一个zval_gc_info结构的宏。zval_gc_info的结构如下:
zend/zend_gc.h文件的91行开始:

 typedef struct _zval_gc_info {
zval z;
union {
gc_root_buffer       *buffered;
struct _zval_gc_info *next;
} u;} zval_gc_info;

zval_gc_info的第一个成员为zval结构,这就确保其和以zval变量分配的内存的开始对齐,从而在zval_gc_info类型指针的强制转换时,其可以作为zval使用。关于gc_root_buffer等将在后面的结构和实现时介绍,它定义的PHP垃圾回收机制的缓存结构。GC_ZVAL_INIT用来初始化替代了zval的zval_gc_info,它会把zval_gc_info中的成员u的buffered字段设置成NULL,此字段仅在将其放入垃圾回收缓冲区时才会有值,否则会一直是NULL。

由于PHP中所有的变量都是以zval变量的形式存在,这里以zval_gc_info替换zval,从而成功实现垃圾收集机制在原有系统中的集成。
这个有点面向对象中多态的感觉。

立即学习PHP免费学习笔记(深入)”;

【垃圾回收机制的存储方式】
结点结构:

 typedef struct _gc_root_buffer {
struct _gc_root_buffer   *prev;/* double-linked list               */
struct _gc_root_buffer   *next;
zend_object_handle        handle;/* must be 0 for zval               */
union {
zval                 *pz;
zend_object_handlers *handlers;
} u;} gc_root_buffer;

很明显(见注释,虽然PHP中的注释很少,但是有些纯粹是纠结的注释),这是一个双向链表。

在联合体中的pz变量很明显就是之前定义的多态的zval_gc_info结构,于是其在链表中的当前结点指针可以通过((zval_gc_info*)(pz))->u.buffered获取,不过在看其源码中有多处使用到这个调用方式,为何不另起一个宏呢?难道是怕宏太多,不是啊,PHP就是以宏多著称,比这个宏嵌套多的宏海了去了。不懂。另外handle等结构是特别针对对象变量的。

缓冲区是话在全局变量中的,和其它模块的全局变量一样,gc也有其自己的全局变量访问宏 GC_G(v),同样对于全局变量访问宏在是否ZTS下有不同的实现。
在zend_gc.h中定义的全局变量如下:

typedef struct _zend_gc_globals {
zend_bool         gc_enabled;/* 是否开启垃圾收集机制 */
zend_bool         gc_active;/* 是否正在进行 */ 
gc_root_buffer   *buf;/* 预分配的缓冲区数组,默认为10000(preallocated arrays of buffers)   */
gc_root_buffer    roots;/* 列表的根结点(list of possible roots of cycles) */
gc_root_buffer   *unused;/* 没有使用过的缓冲区列表(list of unused buffers)           */
gc_root_buffer   *first_unused;/* 指向第一个没有使用过的缓冲区结点(pointer to first unused buffer)   */
gc_root_buffer   *last_unused;/* 指向最后一个没有使用过的缓冲区结点,此处为标记结束用(pointer to last unused buffer)    */ 
zval_gc_info     *zval_to_free;/* 将要释放的zval变量的临时列表(temporaryt list of zvals to free) */
zval_gc_info     *free_list;/* 临时变量,需要释放的列表开头 */
zval_gc_info     *next_to_free;/* 临时变量,下一个将要释放的变量位置*/ 
zend_uint gc_runs;/* gc运行的次数统计 */
zend_uint collected;    /* gc中垃圾的个数 */ // 省略...

【垃圾回收机制中的颜色标记】

知识吐司
知识吐司

专注K12教育的AI知识漫画生成工具

下载
 #define GC_COLOR  0x03 #define GC_BLACK  0x00#define GC_WHITE  0x01#define GC_GREY   0x02#define GC_PURPLE 0x03 #define GC_ADDRESS(v) \
((gc_root_buffer*)(((zend_uintptr_t)(v)) & ~GC_COLOR))#define GC_SET_ADDRESS(v, a) \
(v) = ((gc_root_buffer*)((((zend_uintptr_t)(v)) & GC_COLOR) | ((zend_uintptr_t)(a))))#define GC_GET_COLOR(v) \
(((zend_uintptr_t)(v)) & GC_COLOR)#define GC_SET_COLOR(v, c) \
(v) = ((gc_root_buffer*)((((zend_uintptr_t)(v)) & ~GC_COLOR) | (c)))#define GC_SET_BLACK(v) \
(v) = ((gc_root_buffer*)(((zend_uintptr_t)(v)) & ~GC_COLOR))#define GC_SET_PURPLE(v) \
(v) = ((gc_root_buffer*)(((zend_uintptr_t)(v)) | GC_PURPLE))

在PHP的内存管理中我们也有看到类似的以最后位作为某种类型的标记方式。

这里以内存分配的最后两位作为整个结构的颜色标记。其中
白色表示垃圾
紫色表示已放入缓冲区
灰色表示已经进行了一次refcount的减一操作
黑色是默认颜色,正常

【zval定义的改变】
PHP3.0版本 在zend/zend.h文件中,其定义如下:

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

在php3.0之前的版本,如php5.2.9版本,在zend/zend.h文件中,其定义如下:

struct _zval_struct {
/* Variable information */
zvalue_value value;/* value */
zend_uint refcount;
zend_uchar type;/* active type */
zend_uchar is_ref;};

以上就是本文的全部内容,希望对大家的学习有所帮助,更多相关内容请关注PHP中文网!

相关推荐:

浅谈PHP源码三十二:PHP内存池中的emalloc/efree层与堆(heap)层

浅谈PHP源码三十一:PHP内存池中的堆(heap)层基础

浅谈PHP源码三十:PHP内存池中的存储层

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
c++ 根号
c++ 根号

本专题整合了c++根号相关教程,阅读专题下面的文章了解更多详细内容。

70

2026.01.23

c++空格相关教程合集
c++空格相关教程合集

本专题整合了c++空格相关教程,阅读专题下面的文章了解更多详细内容。

73

2026.01.23

yy漫画官方登录入口地址合集
yy漫画官方登录入口地址合集

本专题整合了yy漫画入口相关合集,阅读专题下面的文章了解更多详细内容。

298

2026.01.23

漫蛙最新入口地址汇总2026
漫蛙最新入口地址汇总2026

本专题整合了漫蛙最新入口地址大全,阅读专题下面的文章了解更多详细内容。

471

2026.01.23

C++ 高级模板编程与元编程
C++ 高级模板编程与元编程

本专题深入讲解 C++ 中的高级模板编程与元编程技术,涵盖模板特化、SFINAE、模板递归、类型萃取、编译时常量与计算、C++17 的折叠表达式与变长模板参数等。通过多个实际示例,帮助开发者掌握 如何利用 C++ 模板机制编写高效、可扩展的通用代码,并提升代码的灵活性与性能。

17

2026.01.23

php远程文件教程合集
php远程文件教程合集

本专题整合了php远程文件相关教程,阅读专题下面的文章了解更多详细内容。

114

2026.01.22

PHP后端开发相关内容汇总
PHP后端开发相关内容汇总

本专题整合了PHP后端开发相关内容,阅读专题下面的文章了解更多详细内容。

79

2026.01.22

php会话教程合集
php会话教程合集

本专题整合了php会话教程相关合集,阅读专题下面的文章了解更多详细内容。

94

2026.01.22

宝塔PHP8.4相关教程汇总
宝塔PHP8.4相关教程汇总

本专题整合了宝塔PHP8.4相关教程,阅读专题下面的文章了解更多详细内容。

74

2026.01.22

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Git 教程
Git 教程

共21课时 | 3万人学习

PHP新手语法线上课程教学
PHP新手语法线上课程教学

共13课时 | 0.9万人学习

php-src源码分析探索
php-src源码分析探索

共6课时 | 0.5万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号