$a=newstdClass;$b=newstdClass;$c=newstdClass;echomemory_get_usage(),PHP_EOL;//706528unset($a);echomemory_get_usage(),PHP_EOL;//706488gc_collect_cycles();echomemory_get_usage(),PHP_EOL;//706488
从上面的代码中可以看出,我们 unset() 掉 $a 之后,内存直接就减少了。但是,如果是产生了循环引用的情形,那么大略的进行 unset() 就没有效果了。
classD{public$d;}$d=newD;$d->d=$d;echomemory_get_usage(),PHP_EOL;//706544unset($d);echomemory_get_usage(),PHP_EOL;//706544gc_collect_cycles();echomemory_get_usage(),PHP_EOL;//706488
在这段代码中,我们对 $d 进行了一个大略的循环引用赋值。利用 unset() 后,内存没有发生变革,这时,只能利用 gc_collect_cycles() 函数来进行逼迫的循环引用清理,才能将 $d 里面的无效循环引用打消掉。
没错,这一段的重点正是 gc_collect_cycles() 这个函数。它在正常情形下对普通的变量引用是不会产生什么清理效果的,当然,对付普通的变量我们直接 unset() 掉就可以了。它最紧张的浸染便是针对循环引用的清理。之前我们学习过,循环引用计数会存在一个 根缓冲区 ,一样平常默认情形下它能容纳 10000 个待清理的 可能根 。而 gc_collect_cycles() 的浸染便是不用等这个 根缓冲区 满就直接进行清理(个人理解)。关于这个垃圾回收算法的内容请移步:PHP垃圾回收机制的一些浅薄理解
实在,大部分情形下我们是不太须要关注 PHP 的垃圾回收问题的,也便是说,我们不是很须要手动地去调用这个 gc_collect_cycles() 函数。PHP-FPM 在每次调用完成后会直接整体的开释,大略的一次 CLI 脚本实行完也会全部开释。没错,正常情形下,PHP 一次实行完成之后就会销毁所有的内容,内存垃圾自然也就不存在了。但是,在实行永劫光的守护脚本时,或者利用常驻进程的框架(Swoole)时,还是须要把稳有没有循环引用的问题。由于这种程序一贯运行,如果存在大量循环引用工具时,就有可能导致内存透露。
开启、关闭及查看循环引用垃圾回收状态gc_disable();echogc_enabled(),PHP_EOL;//gc_enable();echogc_enabled(),PHP_EOL;//1
很大略的三个函数,gc_disable() 是 “停用循环引用网络器”,gc_enable() 是“开启循环引用网络器”,而 gc_enabled() 便是查看当前的循环引用网络器是否开启。
逼迫回收Zend引擎内存管理器利用的内存gc_mem_caches()
官网及网络上并没有什么详细的先容,不过从定义来看,它紧张的浸染便是回收 PHP 底层的 Zend 引擎内存管理器所利用过的内存。这个大家理解下就好,平常也从来没用过。
获取垃圾网络器的信息$e=newstdClass;for($i=100;$i>0;$i--){$e->list[]=$e;}unset($e);gc_collect_cycles();var_dump(gc_status());//array(4){//["runs"]=>int(1)//["collected"]=>int(2)//["threshold"]=>int(10001)//["roots"]=>int(0)//}
我们还是做了一个循环引用的工具,然后利用 gc_status() 来查看当前垃圾回收器中关于循环引用的状态。从返回的内容可以看出, runs 运行了 1 个,collected 网络了 2 个, threshold 阈值是 10001,roots 可能根没有了(已经被回收了)。
这个函数可以在测试环境中对代码的运行情形进行检讨,查看我们代码中有没有不正常的循环引用情形,当然,上面的阐明也只是个人的推测,由于关于这方面的资料确实非常少。以是也希望深入研究过这方面内容的大神能够留言指示迷津!
!
测试代码:
https://github.com/zhangyue0503/dev-blog/blob/master/php/202005/source/PHP%E4%B8%AD%E7%9A%84%E5%9E%83%E5%9C%BE%E5%9B%9E%E6%94%B6%E7%9B%B8%E5%85%B3%E5%87%BD%E6%95%B0.php
参考文档:
PHP的引用计数是什么意思?
PHP垃圾回收机制的一些浅薄理解
https://www.php.net/manual/zh/function.gc-collect-cycles.php
https://www.php.net/manual/zh/function.gc-disable.php
https://www.php.net/manual/zh/function.gc-enable.php
https://www.php.net/manual/zh/function.gc-enabled.php
https://www.php.net/manual/zh/function.gc-mem-caches.php
https://www.php.net/manual/zh/function.gc-status.php