首页 » PHP教程 » php设置头技巧_php7的垃圾收受接收机制二

php设置头技巧_php7的垃圾收受接收机制二

访客 2024-12-05 0

扫一扫用手机浏览

文章目录 [+]

上次学习了PHP通过引用计数自动处理变量的利用,当某个zend_value引用计数变为0时, 当前zend_value就会被销毁,这次来学习第二个方面,自动垃圾回收机制。

这里引用《php7底层设计与源码实现》中的例子

php设置头技巧_php7的垃圾收受接收机制二

$a = [];$a[] = &$a;unset($a);

php设置头技巧_php7的垃圾收受接收机制二
(图片来自网络侵删)

这里数组$a的元素引用了$a自身,造成在unset之后,自身的指向没有肃清,成为垃圾。

紧张构造

# 存放网络的数据# 这是个双向链表typedef struct _gc_root_buffer {zend_refcounted ref;struct _gc_root_buffer next; / double-linked list /struct _gc_root_buffer prev;uint32_t refcount;} gc_root_buffer;# 垃圾网络器紧张构造typedef struct _zend_gc_globals {zend_bool gc_enabled; #是否启用zend_bool gc_active; #是否在运行zend_bool gc_full;#是否满了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 /gc_root_buffer to_free;/ list to free /gc_root_buffer next_to_free;uint32_t gc_runs;uint32_t collected;#if GC_BENCHuint32_t root_buf_length;uint32_t root_buf_peak;uint32_t zval_possible_root;uint32_t zval_buffered;uint32_t zval_remove_from_buffer;uint32_t zval_marked_grey;#endifgc_additional_buffer additional_buffer;} zend_gc_globals;

我们梳理下逻辑:

一个变量在unset之后,如果它指向的zend_value的refcount==0则直接销毁即可,如果refcount>0,那么考试测验进行--refcount操作,如果即是0了,解释它没有其他被指向的,则可以销毁,如果refcount还是>0,则它可能是垃圾,这时候须要放入垃圾回收器中。

static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_CV_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS){USE_OPLINEzval var = EX_VAR(opline->op1.var); # 必须是存在refcount的类型如数组、工具if (Z_REFCOUNTED_P(var)) {zend_refcounted garbage = Z_COUNTED_P(var);ZVAL_UNDEF(var);SAVE_OPLINE(); # 进行refcount - 1操作, =0可以销毁if (!--GC_REFCOUNT(garbage)) {zval_dtor_func(garbage);} else { # refcount>0 可能是垃圾,放入 gc_globals进行处理gc_check_possible_root(garbage);}ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();} else { # 其他类型直接置为is_undef类型ZVAL_UNDEF(var);}ZEND_VM_NEXT_OPCODE();}static zend_always_inline void gc_check_possible_root(zend_refcounted ref){if (GC_TYPE(ref) == IS_REFERENCE) {zval zv = &((zend_reference)ref)->val;if (!Z_REFCOUNTED_P(zv)) {return;}ref = Z_COUNTED_P(zv);} # 是否存在内存透露问题 没看明白if (UNEXPECTED(GC_MAY_LEAK(ref))) {gc_possible_root(ref);}}# 网络程序ZEND_API void ZEND_FASTCALL gc_possible_root(zend_refcounted ref){gc_root_buffer newRoot; # 正在进行gcif (UNEXPECTED(CG(unclean_shutdown)) || UNEXPECTED(GC_G(gc_active))) {return;}# 得是数组、工具ZEND_ASSERT(GC_TYPE(ref) == IS_ARRAY || GC_TYPE(ref) == IS_OBJECT); # 不能是black ,black意味着不是垃圾ZEND_ASSERT(EXPECTED(GC_REF_GET_COLOR(ref) == GC_BLACK));ZEND_ASSERT(!GC_ADDRESS(GC_INFO(ref)));GC_BENCH_INC(zval_possible_root); # 空闲缓冲区的头地址newRoot = GC_G(unused);if (newRoot) { # 如果存在,设置pre指针GC_G(unused) = newRoot->prev;} else if (GC_G(first_unused) != GC_G(last_unused)) { # 解释还存在未利用的区域newRoot = GC_G(first_unused);GC_G(first_unused)++;} else { # 缓冲区已满if (!GC_G(gc_enabled)) {return;}# 主处理逻辑 # GC_REFCOUNT(ref)++; gc_collect_cycles();GC_REFCOUNT(ref)--; if (UNEXPECTED(GC_REFCOUNT(ref)) == 0) {zval_dtor_func(ref);return;}if (UNEXPECTED(GC_INFO(ref))) {return;}newRoot = GC_G(unused);if (!newRoot) {#if ZEND_GC_DEBUGif (!GC_G(gc_full)) {fprintf(stderr, "GC: no space to record new root candidate\n");GC_G(gc_full) = 1;}#endifreturn;}GC_G(unused) = newRoot->prev;}GC_TRACE_SET_COLOR(ref, GC_PURPLE);GC_INFO(ref) = (newRoot - GC_G(buf)) | GC_PURPLE;newRoot->ref = ref;newRoot->next = GC_G(roots).next;newRoot->prev = &GC_G(roots);GC_G(roots).next->prev = newRoot;GC_G(roots).next = newRoot;GC_BENCH_INC(zval_buffered);GC_BENCH_INC(root_buf_length);GC_BENCH_PEAK(root_buf_peak, root_buf_length);}

php7底层设计与源码实现

总结下来便是:

1)对roots环中每个元素进行深度优先遍历,将每个元素中gc_info为紫色的标记元素为灰色,且引用计数减1。

2)扫描roots环中gc_info为灰色的元素,如果创造其引用计数仍旧大于0,解释这个元素还在其他地方利用,那么将其颜色重新标记会玄色,并将其引用计数加1(在第一步有减1操作)。
如果创造其引用计数为0,则将其标记为白色。
该过程同样为深度优先遍历。

3)扫描roots环,将gc_info颜色为玄色的元素从roots移除。
然后对roots中颜色为白色的元素进行深度优先遍历,将其引用计数加1(在第一步有减1操作),然后将roots链表移动到待开释的列表中(to_free)。

4)开释to_free列表的元素。

参考书本:《php7底层设计与源码实现》

标签:

相关文章

IT平台命名艺术,探寻数字时代的品牌魅力

随着互联网技术的飞速发展,IT平台如雨后春笋般涌现。在激烈的市场竞争中,一个独具匠心的平台命名,不仅能够激发用户的兴趣,还能在第一...

PHP教程 2024-12-26 阅读0 评论0

IT归宿保安,守护网络安全,筑起数字长城

随着科技的飞速发展,信息技术已成为当今社会的核心竞争力。在这个信息爆炸的时代,网络安全问题日益凸显,IT归宿保安应运而生,成为维护...

PHP教程 2024-12-26 阅读0 评论0

IT思维,引领未来科技发展的核心驱动力

随着科技的飞速发展,信息技术(IT)已经成为推动社会进步的重要力量。在当今时代,IT思维已经成为一种全新的思考方式,它不仅影响着人...

PHP教程 2024-12-26 阅读0 评论0

IT技术博客,洞察行业动态,引领未来趋势

随着信息技术的飞速发展,IT行业已成为推动全球经济增长的重要力量。在这个日新月异的时代,IT技术博客成为了众多技术爱好者、从业者以...

PHP教程 2024-12-26 阅读0 评论0