its*_*eee 5 php garbage-collection unset
前言:我确实知道'unset'在userland中是如何工作的,但我想知道它是如何在内部工作的.
当在zval结构上调用unset时,它会减少引用计数器(refcount__gc).当refcount__gc达到0时,该变量不再使用,可以删除.问题是它是否总是立即完成,或者在某些情况下它可以在以后由垃圾收集器完成?
我发现了两个相互矛盾的陈述:
unset()正如它的名字所说 - 取消设置一个变量.它不会强制立即释放内存.PHP的垃圾收集器会在看到拟合时执行它 - 尽快意图,因为无论如何都不需要那些CPU周期,或者在脚本耗尽内存之前,无论先发生什么.- Stackoverflow回答提到2009 php.net文档
相反的是:
当refcount达到零时,zval被销毁,它所持有的任何内存现在都是免费的 - 更好地理解PHP的垃圾收集,2012年文章
那么哪一个是正确的,比如PHP 5.3和PHP 5.5?如果可能,也许您可以提供PHP源代码中未设置定义的链接.谢谢!
这两种说法都是对的.
让我解释.(至少从PHP 5.0开始就是这样(以前,我不知道).现在有了phpng,它做了根本性的改变,但是这个原则仍在使用.)
循环垃圾收集器仅用于循环引用.当两个对象包含彼此的引用时,我们通常会有它们.
在这种情况下,refcount__gc永远不会降到零......在其他地方仍有一些参考,正常的ZEND_UNSET_*(星号是ARRAY,OBJ或VAR)不能取消它.所以它必须等待垃圾收集器.
并且出于性能原因,仅定期调用垃圾收集器.
你问过ZEND_UNSET_VAR的定义?http://lxr.php.net/xref/PHP_5_6/Zend/zend_vm_def.h#4069
这里是递减引用等的主要功能:http://lxr.php.net/xref/PHP_5_6/Zend/zend_execute.h#74
因此,如果refcount为零,我们确信没有任何链接到它,我们可以释放它.(第二个陈述:只是在讨论refcount == 0 case)
但是,如果它不为零,我们将变量标记为稍后由循环垃圾收集器检查.(第一声明:未必立即释放)