Java 和 PHP GC 的差异和差异出现的原因
JAVA 的 GC 处理
判断草死掉的两种方式:引用计数和可达性分析
可达性分析对 JAVA 比较好用的原因是 JAVA遵守这面向对象的严格要求,每个变量都被对象包裹,所以每个变量都能通过对象来进行遍历找到,最终判断他们的是否被引用;
但对于 PHP 这类面向过程下构建的面向对象,找变量引用就比较零碎了,所以主要是引用计数为主;
便捷记忆,在一片空地上,死掉的草都清理(标记清除),就会出现零碎的光秃点,随着秃点增多,将不是秃点的草都挪到新的空地(复制),这样腾出的地和秃点合在一起形成新的空地,有些草活得比较久,有些草活得短,根据查看的频次将活得短的聚合在一起,活得长的聚合在一起,就是分代算法。
Java的垃圾回收(Garbage Collection,GC)机制是一种自动管理内存的技术,它负责检测和清理不再被引用的对象,以释放内存并防止内存泄漏。在Java中,开发人员无需手动释放内存,因为这是由垃圾回收器自动完成的。Java的垃圾回收机制主要基于以下两个原则:
-
引用计数(Reference Counting):这是一种简单的垃圾回收方法,它通过跟踪每个对象的引用计数来确定对象是否可以被回收。当引用计数为零时,对象被认为是不再被引用的,可以被回收。然而,这种方法容易出现循环引用问题,因此在Java中并没有广泛使用。
-
可达性分析(Reachability Analysis):这是Java主要使用的垃圾回收方法。它从根对象(如主方法中的局部变量和静态变量)开始,通过引用链追踪对象是否可以被访问。如果一个对象不再通过任何引用链与根对象相连,那么这个对象就被认为是不可达的,可以被回收。
以下是Java中几种主要的垃圾回收算法:
-
标记-清除算法(Mark and Sweep):
- 这是最基本的垃圾回收算法。
- 首先,它通过可达性分析标记所有可达对象。
- 然后,它扫描整个堆,清理未标记的对象。
- 这个算法的问题是会产生内存碎片,可能会导致堆内存不连续,进而影响程序性能。
-
复制算法(Copying):
- 这个算法将堆内存分为两个区域:一半是已使用的区域,一半是空的。
- 它首先在已使用区域进行标记,然后将存活的对象复制到空区域,最后清理已使用区域。
- 这个算法的优点是避免了内存碎片问题,但需要额外的内存用于复制对象。
-
标记-整理算法(Mark and Compact):
- 这个算法结合了标记-清除和复制算法的优点。
- 首先,它标记可达对象,然后将它们压缩到堆的一端,清理掉堆的另一端的垃圾对象。
- 这个算法也可以减少内存碎片,但不需要额外的内存。
-
分代算法(Generational):
- 这个算法根据对象的年龄将堆分成不同的代。
- 年轻代中的对象通常具有较短的生命周期,老年代中的对象具有较长的生命周期。
- 垃圾回收频繁地发生在年轻代,而较少发生在老年代。
- 这个算法利用了对象的特性,提高了回收效率。
PHP 的 GC 处理
PHP 使用引用计数(Reference Counting)作为主要的垃圾回收机制。每个变量和对象在 PHP 中都有一个引用计数器,用于跟踪对象的引用关系。当一个变量或对象的引用计数降为零时,它就会被认为是不再被引用的,可以被垃圾回收。
以下是 PHP 引用计数垃圾回收机制的基本工作原理:
-
引用计数:每当一个变量或对象引用另一个变量或对象时,引用计数会增加1。当一个变量不再引用某个对象时,引用计数会减少1。这个计数器是实时更新的,反映了对象的当前引用情况。
-
回收不可达对象:垃圾回收器会定期检查引用计数,并找出那些引用计数为零的对象。这些对象被认为是不再被引用的,可以安全地回收内存。
-
循环引用问题:引用计数垃圾回收机制对于循环引用问题并不十分有效。循环引用是指一组对象互相引用,导致它们的引用计数永远不会降为零。为了解决这个问题,PHP 引入了周期性垃圾回收(Cycle Collector),它定期检测并处理循环引用。
-
周期性垃圾回收:周期性垃圾回收器负责检测循环引用,并释放被这些循环引用困住的内存。它会在特定的时间间隔内运行,识别并处理循环引用,从而防止内存泄漏。
Python 的 GC 处理
Python 的垃圾回收(Garbage Collection,GC)机制主要基于引用计数和循环垃圾回收两个核心原理,以自动管理内存。以下是 Python 的垃圾回收机制的详细说明:
-
引用计数(Reference Counting):
- Python 中的每个对象都有一个引用计数器,用于跟踪对象的引用关系。
- 当一个对象被引用时,其引用计数会增加1,当一个对象不再被引用时,其引用计数会减少1。
- 当引用计数降为零时,说明对象不再被任何变量或数据结构引用,可以被垃圾回收。
-
循环垃圾回收:
- 引用计数机制可以有效地处理大多数情况,但对于循环引用(两个或多个对象相互引用形成环)的情况无法处理。
- 为了解决循环引用问题,Python 引入了循环垃圾回收器(Cycle Collector)。
- 循环垃圾回收器定期检查引用关系图,找出并清理不可达的循环引用。
-
分代垃圾回收:
- Python 的垃圾回收还引入了分代垃圾回收策略,将对象分为三代:年轻代、中年代和老年代。
- 大部分新创建的对象放入年轻代,如果在几轮垃圾回收后仍然存活,它们会晋升到中年代,然后到老年代。
- 基于分代的策略利用了对象的生命周期模式,提高了垃圾回收的效率。
-
垃圾回收周期:
- Python 的垃圾回收不是持续运行的,而是在特定条件下触发。
- 垃圾回收器会在一组触发条件满足时运行,如年轻代中对象的数量超过阈值、内存分配请求失败等。
- 当触发条件满足时,垃圾回收器会进行一轮或多轮垃圾回收,清理不可达对象。
-
gc模块:- Python 提供了一个名为
gc的模块,用于手动控制和配置垃圾回收机制。 - 开发人员可以使用
gc模块中的函数来手动触发垃圾回收、禁用垃圾回收或配置垃圾回收参数。
- Python 提供了一个名为
PHP GC 和 Python GC 的差异
PHP 和 Python 是两种不同的脚本语言,它们的垃圾回收(GC)算法和策略存在一些差异。以下是 PHP 和 Python 的 GC 算法之间的主要区别:
PHP 的 GC 算法:
-
引用计数:PHP 主要使用引用计数来管理内存。每个变量和对象都有一个引用计数,当引用计数变为零时,变量或对象就被回收。这个方法简单且实时,但容易出现循环引用问题。
-
周期性垃圾回收:为了解决循环引用问题,PHP 引入了周期性垃圾回收(Cycle Collector)。周期性垃圾回收器会定期检查对象之间的引用关系,以便释放不再使用的内存。这是 PHP 针对循环引用问题的一种补救措施。
-
Zend Memory Manager:PHP 使用 Zend Memory Manager 来管理内存。它负责内存分配和释放,以及跟踪引用计数和垃圾回收。Zend Memory Manager 可以通过配置参数来调整垃圾回收行为。
Python 的 GC 算法:
-
引用计数和循环垃圾回收:Python 同样使用引用计数来追踪对象的引用关系。但与 PHP 不同,Python 还实现了循环垃圾回收器,用于检测并处理循环引用。
-
分代垃圾回收:Python 的垃圾回收还引入了分代垃圾回收策略。Python 将对象分为三代:年轻代、中年代和老年代。新创建的对象会放入年轻代,如果经过一定数量的垃圾回收循环后仍然存活,它们会被提升到中年代,以此类推。这个策略利用了观察到的对象生命周期模式,提高了垃圾回收的效率。
-
垃圾回收周期:Python 的垃圾回收器不是定期运行的,而是基于阈值和触发条件来触发的。具体触发条件包括年轻代对象数量、年轻代空间占用率等。这个策略可以降低垃圾回收对性能的影响。
GO 语言的 GC
Go语言(或简称Golang)的垃圾回收(GC)是一种自动管理内存的机制,旨在减轻开发人员手动管理内存的负担,提高程序的可靠性和性能。Go语言的GC机制具有以下特点和原则:
-
并发垃圾回收:Go语言的GC是并发的,这意味着垃圾回收器可以在程序运行的同时执行。它不会导致应用程序停顿(Stop-The-World),因此对于高并发和实时性要求高的应用程序非常适用。
-
分代垃圾回收:Go语言的GC使用分代垃圾回收策略,将堆内存分为三代:新生代、中年代和老年代。新分配的对象通常放入新生代,存活时间较长的对象会升级到中年代和老年代。这种分代策略提高了垃圾回收的效率。
-
标记-清除算法:Go语言的垃圾回收器使用标记-清除(Mark-and-Sweep)算法。它首先标记所有活动对象,然后清除未标记的对象。这个算法能够处理循环引用并有效地回收不再使用的内存。
-
三色标记法:Go语言的GC引入了三色标记法,将对象标记为白色、黑色和灰色。黑色表示已经标记为活动对象,白色表示未标记的对象,灰色表示待处理的对象。这个方法有助于减少标记和清除的阶段。
-
垃圾回收时间控制:Go语言的垃圾回收器可以通过设置环境变量来控制垃圾回收的时间和频率。这使得开发人员可以根据应用程序的需求进行调整,以平衡性能和内存使用。
-
内存分配优化:Go语言的运行时系统还包括了一个内存分配器,它针对小对象和大对象进行了优化,以减少内存碎片和提高分配性能。
都有哪些场景会用到循环引用?
循环引用是指两个或多个对象之间相互引用,形成一个环形的引用关系。这种情况通常不是有意为之,而是一种错误或者设计不当的情况。尽管循环引用通常是不推荐的,但有一些特定的情景可能需要它们,尤其是在某些编程模型或设计中:
-
数据结构中的循环引用:在某些数据结构中,循环引用是有意为之的。例如,双向链表中的每个节点都包含对前一个和后一个节点的引用,因此它们会形成一个环形引用。这种数据结构在某些情况下非常有用。
-
图数据结构:图是由节点和边组成的数据结构,其中节点之间可能存在循环引用。图数据结构通常用于表示网络、关系和复杂的数据关联。在这种情况下,循环引用是必要的。
-
观察者模式:在观察者模式中,主题对象(Subject)和观察者对象(Observer)之间可能存在循环引用。主题对象需要通知观察者对象进行更新,而观察者对象通常也需要引用主题对象以便取消注册。这种情况下,循环引用是合理的。
-
资源管理:某些资源需要引用它们的持有者。例如,一个对象可能需要引用一个打开的文件、数据库连接或网络连接。这种情况下,资源可能会被多个对象持有,形成循环引用,以确保在没有对象引用资源时不会被关闭。
Javascript 循环引用的一个案例
class Subject {constructor() {this.observers = [];}addObserver(observer) {this.observers.push(observer);}notify(message) {this.observers.forEach(observer => {observer.update(message);});}
}class Observer {constructor(name) {this.name = name;}update(message) {console.log(`${this.name} received message: ${message}`);}
}const subject = new Subject();
const observer1 = new Observer("Observer 1");
const observer2 = new Observer("Observer 2");subject.addObserver(observer1);
subject.addObserver(observer2);observer1.subject = subject; // 主题引用了观察者
observer2.subject = subject;subject.notify("Hello, observers!");
在观察者模式中,观察者通常引用主题对象是为了实现以下目的:
-
访问主题数据:观察者需要访问主题对象的数据或状态以执行相应的操作。通过引用主题对象,观察者可以轻松地获取主题的信息。
-
响应主题的变化:观察者的主要任务是响应主题对象的状态变化。通过引用主题对象,观察者可以注册自己,并接收主题的通知,从而知道何时以及如何更新自己。
-
与主题建立松耦合关系:引用主题对象有助于观察者与主题对象之间建立松耦合的关系。观察者不需要了解主题对象的内部实现细节,只需关注主题的状态变化即可
相关文章:
Java 和 PHP GC 的差异和差异出现的原因
JAVA 的 GC 处理 判断草死掉的两种方式:引用计数和可达性分析 可达性分析对 JAVA 比较好用的原因是 JAVA遵守这面向对象的严格要求,每个变量都被对象包裹,所以每个变量都能通过对象来进行遍历找到,最终判断他们的是否被引用&…...
loguru logger使用
一、基本使用 ①标准使用 from loguru import logger# 在标准输出里面输出一行debug日志 logger.debug("Thats dubug")②设置输出格式 from loguru import loggerlogger.remove(0) # 先删除格式 logger.add(sink./logger.log, format"{time: %Y-%m-%d %H:%M…...
vue-自适应布局-postcss-pxtorem
原理: 比如一个375px设计稿 其中一个320px宽度的元素 如何实现自适应布局呢? 其实可以这样理解: 我们先计算出375屏幕时候320px的大小,在屏幕变化时候,这些元素都会等比例缩放 比如屏幕从375 变为750px时候࿰…...
9.12|day 5|day 44 |完全背包| 518. 零钱兑换 II | 377. 组合总和 Ⅳ
● 完全背包 主要是看清01背包和完全背包的区别 //01背包 for(int i 0;i<weight.size();i){ for(int j bagWeight;j>weight[i];j--){dp[j] Math.max(dp[j],dp[j-weight[i]]value[i]); } } //完全背包 for(int i 0;i<weight.size();i){for(int j weight[i];j<…...
C++ 中的原子变量(std::atomic)使用指南
目录 C 中的原子变量(std::atomic)使用指南基本概念使用方法创建原子变量读取值修改值原子操作 常见应用场景1. 计数器2. 控制标志3. 链表和数据结构 示例代码结论 C 中的原子变量(std::atomic)使用指南 原子变量(std…...
【用unity实现100个游戏之9】使用Unity制作类八方旅人、饥荒风格的俯视角2.5D游戏
前言 2.5D游戏 是一种介于二维和三维之间的游戏形式。它通常在二维平面上展示游戏内容,但利用三维技术来实现更加逼真的图像效果。 在2.5D游戏中,角色和环境通常是以平面的形式呈现,但可以在垂直方向上移动。这意味着玩家可以在一个相对较薄…...
如何在群晖中,正确配置 docker 的 ipv6 地址
参考 2023年9月12日 https://synocommunity.com/ https://github.com/wangliangliang2/fix_synology_docker_ipv6 https://post.smzdm.com/p/an3np8m7/ 正文 关于这个话题,国内搜索引擎得到的结果出奇的一致,且过时。 (看的我脑壳痛&#…...
XSS入门 XSS Challenges
level1(直接注入) <script>alert(xss)</script>level2(双引号闭合标签) 测试 <sCr<ScRiPt>IPT>OonN"\/(hrHRefEF)</sCr</ScRiPt>IPT>发现<>"被转换,构造新的语句 "><script>alert(/xss/)</…...
李沐《动手学深度学习》torch.cat() 和 torch.stack()的区别及思考
一、问题引出 好久没更新啦!最近在学习沐神《动手学深度学习》6.5节池化层的时候,发现沐神在两处相似的地方使用了两种Python拼接函数torch.cat()和torch.stack(): 百思不得其解,于是查阅相关文档之后终于弄清楚了两者之间的区别…...
【算法与数据结构】235、LeetCode二叉搜索树的最近公共祖先
文章目录 一、题目二、解法三、完整代码 所有的LeetCode题解索引,可以看这篇文章——【算法和数据结构】LeetCode题解。 一、题目 二、解法 思路分析:本题和这道题类似【算法与数据结构】236、LeetCode二叉树的最近公共祖先,相同的算法也能解…...
bboss 流批一体化框架 与 数据采集 ETL
数据采集 ETL 与 流批一体化框架 特性: 高效、稳定、快速、安全 bboss 是一个基于开源协议 Apache License 发布的开源项目,主要由以下三部分构成: Elasticsearch Highlevel Java Restclient , 一个高性能高兼容性的Elasticsea…...
JVM详细教程
JVM 前言 还在完善中先发布 JVM虚拟机厂家多钟多样,具体实现细节可能不一样,这里主要讲的是虚拟机的规范,以下内容融合了各个平台发布的内容和周志明老师的《深入理解java虚拟机》 JVM概述 如何理解jvm跨平台? 编译成汇编代码…...
Smartbi吴华夫:后疫情时代,BI发展趋势的观察与应对
沿着旧地图找不到新大陆,“基于指标体系的可视化分析和增强分析”成为BI发展新阶段。Smartbi V11系列新品与时俱进,以指标为核心,同时融合BI应用,赋能管理者和业务,成为引领数字化运营的新航标! ——思迈特…...
软件设计模式系列之三———工厂方法模式
1 模式的定义 工厂方法模式是一种常见的设计模式,属于创建型设计模式之一,它在软件工程中用于对象的创建。该模式的主要思想是将对象的创建过程抽象化,将具体对象的实例化延迟到子类中完成,以便在不同情况下可以创建不同类型的对…...
pytorch 多卡分布式训练 调用all_gather_object 出现阻塞等待死锁的问题
pytorch 多卡分布式训练 torch._C._distributed_c10d中的函数all_gather_object 出现阻塞等待死锁的问题 解决办法就是 在进程通信之前调用torch.cuda.set_device(local_rank) For NCCL-based processed groups, internal tensor representations of objects must be moved …...
SpringMvc增删改查
SpringMvc增删改查 一、前期准备二、逆向生成增删改查2.2.aspect切面层2.3.Mybatis generator逆向生成2.4.根据生成代码编写Biz层与实现类 三、controller层代码编写四、前台代码与分页代码五、案例测试 一、前期准备 1.2.导入pom.xml依赖 <?xml version"1.0" …...
【计算机网络】网络编程接口 Socket API 解读(5)
Socket 是网络协议栈暴露给编程人员的 API,相比复杂的计算机网络协议,API 对关键操作和配置数据进行了抽象,简化了程序编程。 本文讲述的 socket 内容源自 Linux man。本文主要对各 API 进行详细介绍,从而更好的理解 socket 编程。…...
手动实现一个bind函数!
原文地址:手动实现一个bind函数! - 知乎 1.bind函数用法 bind()方法用于创建一个新的函数,这个新函数接收的第一个参数代表的就是this,利用bind()函数我就就可以任意改变函数内部的this指向了。 官网的解释: bind()…...
数据结构-时间复杂度/空间复杂度
Hello,好久没有更新了哦,已经开始学习数据结构了,这篇文章呢就是对刚学数据结构所接触到的时间复杂度进行一个分享哦,如果有错误之处,大家记得拍拍我哦~ 既然要讨论时间/空间复杂度,那我们就得知道时间/空…...
英语写作中“展示”、“表明”demonstrate、show、indicate、illustrate的用法
一、demonstrate、show、indicate在论文写作中主要用法是:demonstrate/show/indicate 从句: Sb./Sth. demonstrates/shows/indicates that ……从句中一般表达事实、观点和结论等。 例句: The authors demonstrated/showed/indicated that…...
基于距离变化能量开销动态调整的WSN低功耗拓扑控制开销算法matlab仿真
目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.算法仿真参数 5.算法理论概述 6.参考文献 7.完整程序 1.程序功能描述 通过动态调整节点通信的能量开销,平衡网络负载,延长WSN生命周期。具体通过建立基于距离的能量消耗模型&am…...
R语言AI模型部署方案:精准离线运行详解
R语言AI模型部署方案:精准离线运行详解 一、项目概述 本文将构建一个完整的R语言AI部署解决方案,实现鸢尾花分类模型的训练、保存、离线部署和预测功能。核心特点: 100%离线运行能力自包含环境依赖生产级错误处理跨平台兼容性模型版本管理# 文件结构说明 Iris_AI_Deployme…...
Linux相关概念和易错知识点(42)(TCP的连接管理、可靠性、面临复杂网络的处理)
目录 1.TCP的连接管理机制(1)三次握手①握手过程②对握手过程的理解 (2)四次挥手(3)握手和挥手的触发(4)状态切换①挥手过程中状态的切换②握手过程中状态的切换 2.TCP的可靠性&…...
前端导出带有合并单元格的列表
// 导出async function exportExcel(fileName "共识调整.xlsx") {// 所有数据const exportData await getAllMainData();// 表头内容let fitstTitleList [];const secondTitleList [];allColumns.value.forEach(column > {if (!column.children) {fitstTitleL…...
如何为服务器生成TLS证书
TLS(Transport Layer Security)证书是确保网络通信安全的重要手段,它通过加密技术保护传输的数据不被窃听和篡改。在服务器上配置TLS证书,可以使用户通过HTTPS协议安全地访问您的网站。本文将详细介绍如何在服务器上生成一个TLS证…...
[Java恶补day16] 238.除自身以外数组的乘积
给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法,且在 O(n) 时间复杂度…...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...
Reasoning over Uncertain Text by Generative Large Language Models
https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829 1. 概述 文本中的不确定性在许多语境中传达,从日常对话到特定领域的文档(例如医学文档)(Heritage 2013;Landmark、Gulbrandsen 和 Svenevei…...
iOS性能调优实战:借助克魔(KeyMob)与常用工具深度洞察App瓶颈
在日常iOS开发过程中,性能问题往往是最令人头疼的一类Bug。尤其是在App上线前的压测阶段或是处理用户反馈的高发期,开发者往往需要面对卡顿、崩溃、能耗异常、日志混乱等一系列问题。这些问题表面上看似偶发,但背后往往隐藏着系统资源调度不当…...
20个超级好用的 CSS 动画库
分享 20 个最佳 CSS 动画库。 它们中的大多数将生成纯 CSS 代码,而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库,可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画,可以包含在你的网页或应用项目中。 3.An…...
