php 垃圾回收
来源: http://php.net/manual/zh/features.gc.refcounting-basics.php
<?php $a = "new string"; $b = $a; xdebug_debug_zval( ‘a‘ ); ?>
a: (refcount=2, is_ref=0)=‘new string‘
当任何关联到某个变量容器的变量离开它的作用域 (比如: 函数执行结束), 或者对变量调用了函数 unset()时, refcount 就会减 1
普通的引用计数法会把引用为 0 的 马上清除 (不清楚是多久, 反正很快), 浪费时间
来源: http://php.net/manual/en/features.gc.collecting-cycles.php
为避免不得不检查所有引用计数可能减少的垃圾周期, 引用计数浪费时间
To avoid having to call the checking of garbage cycles with every possible decrease of a refcount, the algorithm instead puts all possible roots (zvals) in the "root buffer" (marking them "purple"). It also makes sure that each possible garbage root ends up in the buffer only once. Only when the root buffer is full does the collection mechanism start for all the different zvals inside. See step A in the figure above.
当根缓冲区满了之后, 检查所有的 引用根节点, 标记为紫色, 每个节点标记一次
In step B, the algorithm runs a depth-first search on all possible roots to decrease by one the refcounts of each zval it finds, making sure not to decrease a refcount on the same zval twice (by marking them as "grey").
让每个节点的引用减一, 通过把访问过的节点设置为灰色, 来确保不会删除同一个根节点两次 深度优先搜索
In step C, the algorithm again runs a depth-first search from each root node, to check the refcount of each zval again. If it finds that the refcount is zero, the zval is marked "white" (blue in the figure). If it‘s larger than zero, it reverts the decreasing of the refcount by one with a depth-first search from that point on, and they are marked "black" again.
如果引用是 0, 蓝色 (表示不可达), 表示要被垃圾回收器删除. (小于 0 也行吧, 有可能本身就是 0, 执行减一之后变成-1)
如果引用大于 0, 那些灰色的点, 让他们的引用加 1
In the last step (D), the algorithm walks over the root buffer removing the zval roots from there, and meanwhile, checks which zvals have been marked "white" in the previous step. Every zval marked as "white" will be freed
在来一次遍历, 删除白色节点
php.ini
zend.enable_gc = On
根缓存区有固定的大小, 可存 10000 个可能根, 当然你可以通过修改 PHP 源码文件 Zend/zend_gc.c
中的常量 GC_ROOT_BUFFER_MAX_ENTRIES
gc_enable()
和 gc_disable()
函数
调用 gc_collect_cycles()
函数强制执行周期回收
在你调用 gc_disable() 函数释放内存之前, 先调用 gc_collect_cycles() 函数可能比较明智