php 7.4.26 使用基于引用计数+同步循环回收的混合gc机制,核心为改进版三色标记-清除算法,支持根缓冲区、手动/自动触发及完整循环检测,不支持分代或增量gc。

PHP 7.4.26 使用的垃圾回收(GC)算法是 基于引用计数(Reference Counting) + 同步循环回收(Synchronous Cycle Collection)的混合机制,其核心实现源自论文 “Practical Cycle Collection for C++” 的改进版三色标记-清除算法,而非传统意义上的“分代”或“增量”GC。
该版本未引入 PHP 8.0+ 的「根缓冲区延迟提交优化」或「弱引用 WeakReference 的 GC 协同机制」,但已完整支持:
- ✅
zend.enable_gc控制开关 - ✅ 根缓冲区(Root Buffer)默认容量为 10,000 个节点
- ✅ 三色标记(White/Gray/Black)识别不可达循环结构
- ✅ 手动调用
gc_collect_cycles()强制触发完整周期 - ✅ 自动触发条件:根缓冲区满(
GC_G(buf)->used == GC_G(buf)->size)
关键源码路径(PHP 7.4.26):
-
Zend/zend_gc.c:主 GC 实现,含gc_collect_cycles()、zval_scan()、gc_mark_grey()等 -
Zend/zend_types.h:定义zval.u1.gc_info和GC_INFO()宏,用于标记 zval 是否在根缓冲区中 -
Zend/zend_variables.h:zval_dtor()中判断Z_REFCOUNTED()并触发gc_possible_root()
算法执行逻辑简述:
- 当
unset($a)或变量离开作用域时,若Z_REFCOUNTED(zv) && Z_REFCOUNT(zv) == 0→ 直接释放(非循环场景) - 若
Z_REFCOUNT(zv) > 0但已无外部可达路径(如$a->b = $b; $b->a = $a; unset($a,$b)),则调用gc_possible_root(zv)将其加入根缓冲区 - 缓冲区满或显式调用时,进入
gc_collect_cycles():- 将所有根缓冲区节点标为 Gray
- 遍历 Gray 节点的子引用,递归标灰;处理完标 Black
- 最终仍为 White 的节点 → 不可达 → 批量释放
注意:PHP 7.4.26 不使用分代(Generational)GC,也不支持并发标记。所谓“三代”说法常见于误读——PHP 官方从未在 7.x 系列中实现分代收集,该特性仅存在于部分第三方扩展或社区讨论中。
另外,WeakReference 类虽在 PHP 7.4 引入,但它本身不参与 GC 标记过程,仅提供对对象的非持有性访问,其底层仍依赖常规 refcount 与 cycle collector 协同工作。
本质上,PHP 7.4.26 的 GC 是一个保守但可靠的同步周期检测器,专注解决循环引用这一唯一引用计数失效场景。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











