PHP中的垃圾回收相关函数
之前我们已经学习过 PHP 中的引用计数以及垃圾回收机制的概念。这些内容非常偏理论,也是非常常见的面试内容。而今天介绍的则是具体的关于垃圾回收的一些功能函数。关于之前的两篇介绍文章,大家可以到文章底部查看。
再谈循环引用以及强制清理循环引用
我们为什么要强调 “循环引用” 呢?其实,在默认情况下,我们直接 unset() 掉一个没有被其他变量引用的变量时,就会让这个变量的引用计数变为0。这时,PHP 默认的垃圾回收机制就会直接清除掉这个变量。比如:
$a = new stdClass;
$b = new stdClass;
$c = new stdClass;
echo memory_get_usage(), PHP_EOL; // 706528
unset($a);
echo memory_get_usage(), PHP_EOL; // 706488
gc_collect_cycles();
echo memory_get_usage(), PHP_EOL; // 706488
从上面的代码中可以看出,我们 unset() 掉 $a 之后,内存直接就减少了。但是,如果是产生了循环引用的情况,那么简单的进行 unset() 就没有效果了。
class D{
public $d;
}
$d = new D;
$d->d = $d;
echo memory_get_usage(), PHP_EOL; // 706544
unset($d);
echo memory_get_usage(), PHP_EOL; // 706544
gc_collect_cycles();
echo memory_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();
echo gc_enabled(), PHP_EOL; //
gc_enable();
echo gc_enabled(), PHP_EOL; // 1
很简单的三个函数,gc_disable() 是 “停用循环引用收集器”,gc_enable() 是“开启循环引用收集器”,而 gc_enabled() 就是查看当前的循环引用收集器是否开启。
强制回收Zend引擎内存管理器使用的内存
gc_mem_caches()
官网及网络上并没有什么详细的介绍,不过从定义来看,它主要的作用就是回收 PHP 底层的 Zend 引擎内存管理器所使用过的内存。这个大家了解下就好,平常也从来没用过。
获取垃圾收集器的信息
$e = new stdClass;
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://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
PHP中的垃圾回收相关函数的更多相关文章
- .NET中的垃圾回收
目录 l 导言 l 关于垃圾回收 l 垃圾回收算法 m 应用程序根(Application Roots) l 实现 m ...
- JVM调优-Jva中基本垃圾回收算法
从不同的的角度去划分垃圾回收算法. 按照基本回收策略分 引用计数(Reference Counting) 比较古老的回收算法.原理是此对象有一个引用,即增加一个计数,删除一个引用则减少一个计数.垃圾回 ...
- 浅谈Chrome V8引擎中的垃圾回收机制
垃圾回收器 JavaScript的垃圾回收器 JavaScript使用垃圾回收机制来自动管理内存.垃圾回收是一把双刃剑,其好处是可以大幅简化程序的内存管理代码,降低程序员的负担,减少因 长时间运转而带 ...
- 浅谈V8引擎中的垃圾回收机制
最近在看<深入浅出nodejs>关于V8垃圾回收机制的章节,转自:http://blog.segmentfault.com/skyinlayer/1190000000440270 这篇文章 ...
- 【java虚拟机序列】java中的垃圾回收与内存分配策略
在[java虚拟机系列]java虚拟机系列之JVM总述中我们已经详细讲解过java中的内存模型,了解了关于JVM中内存管理的基本知识,接下来本博客将带领大家了解java中的垃圾回收与内存分配策略. 垃 ...
- Python中的垃圾回收与del语句
python中的垃圾回收采用计数算法 一个对象如果被引用N次,则需要N次(即计算引用次数为零时)执行del 才能回收此对象. a = 100 b = a del a print(b) print(a) ...
- 浅谈jvm中的垃圾回收策略
下面小编就为大家带来一篇浅谈jvm中的垃圾回收策略.小编觉得挺不错的,现在就分享给大家,也给大家做个参考.一起跟随小编过来看看吧 java和C#中的内存的分配和释放都是由虚拟机自动管理的,此前我已 ...
- Unity优化方向——优化Unity游戏中的垃圾回收(译)
介绍 当我们的游戏运行时,它使用内存来存储数据.当不再需要该数据时,存储该数据的内存将被释放,以便可以重用.垃圾是用来存储数据但不再使用的内存的术语.垃圾回收是该内存再次可用以进行重用的进程的名称. ...
- 深入理解Node.js中的垃圾回收和内存泄漏的捕获
深入理解Node.js中的垃圾回收和内存泄漏的捕获 文章来自:http://wwsun.github.io/posts/understanding-nodejs-gc.html Jan 5, 2016 ...
随机推荐
- MySQL-19-分布式架构MyCat
MyCAT基础架构图(实验环境) MyCAT实验环境准备 1 环境准备 两台虚拟机: db01(10.0.0.51) db02(10.0.0.52) 每台创建四个mysql实例:3307 3308 3 ...
- Python语言系列-04-高阶函数
闭包 #!/usr/bin/env python3 # author:Alnk(李成果) # 什么是闭包 # 1,闭包存在于函数中 # 2,闭包就是内层函数对外层函数(非全局变量)的引用 # 3,最内 ...
- Kurento实战之三:知识点小导游
欢迎访问我的GitHub https://github.com/zq2599/blog_demos 内容:所有原创文章分类汇总及配套源码,涉及Java.Docker.Kubernetes.DevOPS ...
- OSPF的Router-Id
一.实验拓扑 二.实验编址 三.实验步骤: 1.设置PC的IP等信息 2.启动设备(全选) 3.根据实验编址配置路由器端口IP(先不设置lookback端口) R1: R2: R3: R4: 看一下r ...
- NOIP 模拟 $16\; \rm Star Way To Heaven$
题解 \(by\;zj\varphi\) 看懂题!!! 从最左穿到最右,一定会经过两个星星之间或星星和边界之间,那么我们穿过时当前最优一定是走中点 而我们要求最小的距离最大,那么我们将所有星星和边界( ...
- docker harbor安装
# 官网下载离线包,https://github.com/goharbor/harbor/releases src]# tar xf harbor-offline-installer-v1.8.3.t ...
- ManagementEventWatcher throws ManagementException with call to Stop()
参考网址:https://stackoverflow.com/questions/46100105/managementeventwatcher-throws-managementexception- ...
- JDBC中级篇(MYSQL)——模拟从数据库中上传下载附件
注意:其中的JdbcUtil是我自定义的连接工具类:代码例子链接: package b_blob_clob; import java.io.BufferedOutputStream; import j ...
- Hibernate之关联关系
时间:2017-1-20 16:28 --一对多配置1.第一步:创建实体类 * 客户实体 * 订单实体 示例代码: /** * 客户实体 ...
- vue组件里不用的css还在搜索过滤来删除?试一下vue-clearcss吧!
这篇文章其实是推广介绍我个人的npm工具库,但你不会后悔点进来的(应该吧...)vue-clearcss 为什么要用它? 一个vue文件在长期迭代中css会越来越冗余,它不像html和js那么好删除, ...