引用计数 vs. GC
内存管理问题
内存管理是编程过程中的一个经典问题,早期在 C 语言时代,几乎都靠 malloc/free 手动管理内存。随着各个平台的发展,到现在被广泛采用的主要有两个方法:
- 引用计数 (ARC,Automatic Reference Counting)
- GC (Garbage Collection)
管理方法 ARC/GC
因为 Java 的流行,GC 被广泛的认知。GC 简单的说是定期查找不再使用的对象,释放对象占用的内存。
基于 GC,申请的对象不需要手动释放,只需要确认对象在不再需要时,不再被其他对象引用。
引用计数早期主要用于底层系统,比如文件系统的 inode 管理,后来 C++ 的 boost 库实现了一套完整的 ARC,目前流行的系统还有 Objective C 也是采用的 ARC。
ARC 的特点是,一个对象被引用时,引用计数增加 1,引用对象释放时,引用计数减少 1,如果引用计数为 0,释放对象。
比较
因为 ARC 和 GC 的不同策略,对编程的几个方面的影响。
性能
GC 需要一套额外的系统跟踪分配的内存,分析哪些内存需要释放,相对来说就需要更多的计算。这也是为什么对性能敏感的场景不采用 GC 的原因,比如,高性能的服务端程序,资源有限的嵌入式设备(iOS 就没有采用 GC)。
ARC 由开发者自己来管理资源在什么时候释放,不需要额外的资源,所以性能没有损失。
延迟
GC 回收内存时,需要完全暂停当前程序,这会给程序带来难以预测的一个延迟期。如果需要回收的资源很多,这个延迟可能会非常大。
ARC 在资源引用为 0 时立即释放,没有不可预测的延迟。
编程难度
不难看出,GC 在性能、延迟等方面有明显的缺点,为什么 GC 还会被广泛采用呢?
GC 带来的最大好处是不需要开发者手动管理内存分配,这大大降低了编程难度,同时可以大幅减少跟内存管理相关的 Bug:
- 悬空指针。指针指向的内存被其他代码释放
- 重复释放内存
- 内存泄漏。申请的内存没释放
不过使用 GC 并不代表可以完全不用理解内存管理,如果对象的引用关系跟想象的不一致,GC 也会有内存泄漏的问题。
我们之前理解的内存泄漏 是指一个分配的内存没有被释放造成的。而 GC 平台下的内存泄漏是指对象有引用而开发者不知道,比如:
ObjectA -> ObjectB
ObjectB 使用完后,我们没有及时把 ObjectA 引用 ObjectB 的指针设置为 NULL,这时, ObjectB 不会被 GC 回收。
- 对比表格
| 时机 | 性能 | 延迟 | 编程难度 | |
| ARC | 引用计数为 0 马上回收 | 快 | 小 | 较大 |
| GC | 定时扫描清理 | 慢 | 大 | 较小 |
怎么选择 ARC or GC
开发一个项目时,采用什么样的平台,跟实际面对的场景有很大关系,没有一个技术是用来解决所有问题的。
一般来说,对延迟和性能不敏感的系统,可以考虑带 GC 的平台,比如 Java、Go 等来开发,通常可以提高开发效率。
如果需要对系统的性能有良好的控制,或者平台的资源有限,ARC 是更好的选择。比如操作系统、数据库等选择 C 或者 C++。比如 iOS 的 Object C 就是采用 ARC,实际来看比使用 Java (GC) 的 Android 平台的表现要好太多。
但是 ARC 平台一般对开发者要求要更高。
最近出现的新语言 Rust 采用的是 ARC,但是 Rust 会在代码编译阶段对内存、指针的使用做严格的分析和检查,确保程序没有内存管理问题。相当于把 GC 的一部分工作移到编译阶段,这样程序的运行性能几乎没有损失,同时又大大减少内存管理相关的 Bug。
我的观察从 C++11 正式吸纳 boost 的 smart pointer 后,C++ 在内存管理方面比之前有极大的提升,如果严格的按照 smart pointer 的规范,同样可以减少内存管理的风险。Rust 就有点像一个严格的 C++11 编译系统。
支持 GC 的平台里面有一个特殊的,就是 Erlang。Erlang 的 GC 是进程级别的(Erlang 的轻量级进程),意味着 GC 发生时,只暂停当前进程,其他进程不受影响。另外,Erlang 程序往往会运行海量的进程,相当于把 GC 分散开了,所以 Erlang 的 GC 一般不会产生明显的延迟。
了解这些细节,在面对具体问题时,能帮你做出正确的选择。
欢迎来微博留下您的意见:http://weibo.com/2255454164/E48lBE9pU
weibo: @Tiger_张虎, 云巴 (https://yunba.io) 创始人,yunba.io 云端实时消息服务。 JPush 创始人,原CTO。 Oracle VM 创始团队成员。
引用计数 vs. GC的更多相关文章
- 引用计数gc机制使用不当导致内存泄漏
上一篇文章找同事review了一下,收到的反馈是铺垫太长了,我尽量直入正题,哈哈 最近dbd压测时发现内存泄漏,其实这个问题去年已经暴露了,参见这篇博客[压测周].当时排查不够仔细,在此检讨下.关于d ...
- 2. 引用计数法(Reference Counting)
1960年,George E. Collins 在论文中发布了引用计数的GC算法. 引用计数法意如了一个概念,那就是"计数器",计数器表示的是对象的人气指数, 也就是有多少程序引用 ...
- JVM探究 面试题 JVM的位置 三种JVM:HotSpot 新生区 Young/ New 养老区 Old 永久区 Perm 堆内存调优GC的算法有哪些?标记清除法,标记压缩,复制算法,引用计数法
JVM探究 面试题: 请你弹弹你对JVM的理解?Java8虚拟机和之前的变化更新? 什么是OOM?什么是栈溢出StackOverFlowError?怎么分析 JVM的常用调优参数有哪些? 内存快照如何 ...
- iOS开发--引用计数与ARC
以下是关于内存管理的学习笔记:引用计数与ARC. iOS5以前自动引用计数(ARC)是在MacOS X 10.7与iOS 5中引入一项新技术,用于代替之前的手工引用计数MRC(Manual Refer ...
- Objective-C内存管理之-引用计数
本文会继续深入学习OC内存管理,内容主要参考iOS高级编程,Objective-C基础教程,疯狂iOS讲义,是我学习内存管理的笔记 内存管理 1 内存管理的基本概念 1.1 Objective-C中的 ...
- Python 对象的引用计数和拷贝
Python 对象的引用计数和拷贝 Python是一种面向对象的语言,包括变量.函数.类.模块等等一切皆对象. 在python中,每个对象有以下三个属性: 1.id,每个对象都有一个唯一的身份标识自己 ...
- c++垃圾回收代码练习 引用计数
学习实践垃圾回收的一个小代码 采用引用计数 每次多一个指针指向这个分配内存的地址时候 则引用计数加1 当计数为0 则释放内存 他的难点在于指针之间的复制 所有权交换 计数的变化 #include &l ...
- Python之美[从菜鸟到高手]--一步一步动手给Python写扩展(异常处理和引用计数)
我们将继续一步一步动手给Python写扩展,通过上一篇我们学习了如何写扩展,本篇将介绍一些高级话题,如异常,引用计数问题等.强烈建议先看上一篇,Python之美[从菜鸟到高手]--一步一步动手给Pyt ...
- Python的垃圾回收机制(引用计数+标记清除+分代回收)
一.写在前面: 我们都知道Python一种面向对象的脚本语言,对象是Python中非常重要的一个概念.在Python中数字是对象,字符串是对象,任何事物都是对象,而它们的核心就是一个结构体--PyOb ...
随机推荐
- Atitti 跨语言异常的转换抛出 java js
Atitti 跨语言异常的转换抛出 java js 异常的转换,直接反序列化为json对象e对象即可.. Js.没有完整的e机制,可以参考java的实现一个stack层次机制的e对象即可.. 抛出Ru ...
- hadoop本地库与系统版本不一致引起的错误解决方法
hadoop本地库与系统版本不一致引起的错误解决方法 部署hadoop的集群环境为 操作系统 centos 5.8 hadoop版本为cloudera hadoop-0.20.2-cdh3u3 集 ...
- 每天一个linux命令(24):Linux文件类型与扩展名
Linux文件类型和Linux文件的文件名所代表的意义是两个不同的概念.我们通过一般应用程序而创建的比如file.txt.file.tar.gz ,这些文件虽然要用不同的程序来打开,但放在Linux文 ...
- Microsoft Visual Studio正忙解决办法
问题描述 前段时间用vs2015进行开发.出现如下问题,关闭vs进程重启vs还是无法解决. 如何解决 进入本地项目.vs文件夹 这个文件夹下有个.suo文件,删除该文件,用任务管理器杀掉vs的进程,重 ...
- ValidationSummary控件不弹出错误提示框
采用VS2013 编写的前台,运用ValidationSummary控件时,不出现错误弹窗,网上找到了解决方法 发现是ASP.NET 4.5对验证控件的影响(兼容性),使用ASP.NET 4.5的解决 ...
- Oracle Dataguard之failover
Oracle Dataguard中,角色转换包含两类:Switchover和Failover.上文<Oracle Dataguard之switchover>中,我们已经谈过了switcho ...
- Tools - Git与GitHub
Git Wiki - Git 开源的分布式版本控制系统,用于敏捷高效地管理项目版本. Git - HomePage Git - CHEAT SHEET git_cheat_sheet.pdf GitH ...
- 24个 HTML5 & CSS3 下拉菜单效果及制作教程
下拉菜单是一个很常见的效果,在网站设计中被广泛使用.通过使用下拉菜单,设计者不仅可以在网站设计中营造出色的视觉吸引力,但也可以为网站提供了一个有效的导航方案.使用 HTML5 和 CSS3 可以更容易 ...
- 别用symbolicatecrash来解析crash Log了
今天突然发现了一个解析iOS crash log的好方法,忍不住来分享一下. 相信每个做iOS开发的TX都应该不会对symbolicatecrash陌生,我们第一次遇到真机上产生的崩溃日志时,在网上搜 ...
- Sass细节一变量
同步发布在个人站 变量 局部变量和全局变量的定义 Sass的变量是用$申明的,有局部变量(选择器内部的变量)和全局变量(不在任何选择器内的变量).例如: //这里$width就是全局变量 $width ...