热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

开发笔记:PHP中的垃圾回收相关函数

篇首语:本文由编程笔记#小编为大家整理,主要介绍了PHP中的垃圾回收相关函数相关的知识,希望对你有一定的参考价值。之前我们已经学习过

篇首语:本文由编程笔记#小编为大家整理,主要介绍了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://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

===========

各自媒体平台均可搜索【硬核项目经理】


推荐阅读
  • faster rcnn如何生成anchors
       本文就fasterrcnn中anchors的函数generate_anchors.py为例,介绍anchors的生成过程。   首先看下主函数入口。论文中提到a ... [详细]
  • Tencent APIJSON自动化接口和文档 ORM 库开源啦
    APIJSON是一种专为API而生的JSON网络传输协议以及基于这套协议实现的ORM库。为简单的增删改查、复杂的查询、简单的事务操作提供了完全自动化的API。能大幅降低开发和沟通成 ... [详细]
  • Java验证码——kaptcha的使用配置及样式
    本文介绍了如何使用kaptcha库来实现Java验证码的配置和样式设置,包括pom.xml的依赖配置和web.xml中servlet的配置。 ... [详细]
  • 本文介绍了如何使用PHP向系统日历中添加事件的方法,通过使用PHP技术可以实现自动添加事件的功能,从而实现全局通知系统和迅速记录工具的自动化。同时还提到了系统exchange自带的日历具有同步感的特点,以及使用web技术实现自动添加事件的优势。 ... [详细]
  • 从零开始的ESP8266探索(15)WiFi其他方法和WiFi事件响应
    文章目录目的WiFi其他方法WiFi事件响应事件列表注册事件使用示例总结目的WiFi在使用过程中并非会一直如希望般稳定运行的,为了应对这些情况就需要能够了解WiFi ... [详细]
  • requestLayout()引起的问题网上有大量写的很深入的requestLayout()源码分析的文章。故这里不再写了,只做一个实际情况下遇到的问题的分析。起因:自定义了一个C ... [详细]
  • 拯救万千学子于水深火热之中!Facebook开源无梯度优化工具
    乾明发自凹非寺量子位出品|公众号QbitAI机器学习啥最苦?十有八九找参数!不少研究生,都被卡在这个环节上,久久不能毕业。现 ... [详细]
  • 本文详细介绍了SQL日志收缩的方法,包括截断日志和删除不需要的旧日志记录。通过备份日志和使用DBCC SHRINKFILE命令可以实现日志的收缩。同时,还介绍了截断日志的原理和注意事项,包括不能截断事务日志的活动部分和MinLSN的确定方法。通过本文的方法,可以有效减小逻辑日志的大小,提高数据库的性能。 ... [详细]
  • GetWindowLong函数
    今天在看一个代码里头写了GetWindowLong(hwnd,0),我当时就有点费解,靠,上网搜索函数原型说明,死活找不到第 ... [详细]
  • 本文介绍了在Python3中如何使用选择文件对话框的格式打开和保存图片的方法。通过使用tkinter库中的filedialog模块的asksaveasfilename和askopenfilename函数,可以方便地选择要打开或保存的图片文件,并进行相关操作。具体的代码示例和操作步骤也被提供。 ... [详细]
  • 云原生边缘计算之KubeEdge简介及功能特点
    本文介绍了云原生边缘计算中的KubeEdge系统,该系统是一个开源系统,用于将容器化应用程序编排功能扩展到Edge的主机。它基于Kubernetes构建,并为网络应用程序提供基础架构支持。同时,KubeEdge具有离线模式、基于Kubernetes的节点、群集、应用程序和设备管理、资源优化等特点。此外,KubeEdge还支持跨平台工作,在私有、公共和混合云中都可以运行。同时,KubeEdge还提供数据管理和数据分析管道引擎的支持。最后,本文还介绍了KubeEdge系统生成证书的方法。 ... [详细]
  • 本文介绍了数据库的存储结构及其重要性,强调了关系数据库范例中将逻辑存储与物理存储分开的必要性。通过逻辑结构和物理结构的分离,可以实现对物理存储的重新组织和数据库的迁移,而应用程序不会察觉到任何更改。文章还展示了Oracle数据库的逻辑结构和物理结构,并介绍了表空间的概念和作用。 ... [详细]
  • PyTorch框架中有一个非常重要且好用的包:torchvision,该包主要由3个子包组成,分别是:torchvision.datasets、torchvision.models、torchv ... [详细]
  • 原文:http:blog.linjunhalida.comblogpjaxgithub:https:github.comdefunktjquery-pjax ... [详细]
  • MySQL 的 NULL 值是怎么存储的?
    MySQL 的 NULL 值是怎么存储的? ... [详细]
author-avatar
sunshinena
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有