团队项目中用Go的地方越来越多,最近打算在业余时间好好看看Golang的虚拟机实现。像Java/C#/Python一样,Go的优势之一就是将开发人员从繁重的内存管理中解放 出来,本文对编程语言中常见的垃圾回收技术做一个简要的笔记。

1 Introduction

垃圾回收是一种自动的内存管理技术,它的主要任务就是防止应用程序无休止地向操作系统或Glibc不停地申请内存。通常的做法是将程序不再使用的内存释放给操作 系统或运行时环境,或者回收后重复利用。垃圾回收是John McCarthy同学于1959年在Lisp语言中发明。 由于引入了额外的工作,垃圾回收不可避免地会影响应用进程的实际执行时间,而且它的实现对程序性能有较大的影响。垃圾回收通常都指内存资源的回收,一些其他 的资源,如网络连接、数据库连接、文件描述符等不是垃圾回收的管辖范围。

2 Principles

垃圾回收的基本原则是:

  • 找出应用进程不再需要的数据对象
  • 回收这些对象占用的内存

3 Advantages

垃圾回收能有效地减少因为管理内存引起的Bug:

  • 悬挂指针
  • 多次释放同一块内存
  • 防止内存泄漏

4 Disadvantages

事务总有两面性,垃圾回收不可避免地会带来如下缺陷:

  • 消耗系统的计算资源。因为垃圾回收需要对已分配的对象做额外的处理(如增加引用计数等),而且在回收算法会相当耗时。有研究称,垃圾回收会占用五倍于传统内存管理的时间。
  • 垃圾回收所消耗的时间不可测。对于一些实时性要求较高的系统来说,这简直是噩梦。
  • 如果在有自动垃圾回收的系统中还允许手动回收内存资源。这会是垃圾回收变得更加复杂和扑朔迷离。

5 常见的垃圾回收技术

 

5.1 跟踪式垃圾回收

跟踪式垃圾回收是最常用的垃圾回收技术。它的主要原则是从程序栈的若干个根对象出发,构造一个可达链,对于那些不可达的内存对象,做回收。 如果一个内存对象有被程序中的至少一个变量引用(直接指向或间接指向),则认为该对象可达,否则认为该对象不可达,可以被垃圾回收。

5.1.1 基本算法

 
  1. 标记清除(mark-and-sweep)

    基本思路是遍历以对象为节点、以引用为边构成的图,把所有可以访问到的对象打上标记,然后清扫一遍内存空间,把所有没标记的对象释放。它最大的问题是无法处理 循环引用的问题,而且在GC时,需要程序中断一段时间来清理内存。

  2. 三色标记法(triple-color-marking)

    应用程序的内存对象会被分发到三个集合中,它们分别是(下面将内存对象统称为元素):

    • The Write Set(白色集合)。这个集合中的元素是要被回收的
    • The Black Set(黑色集合)。这个集合中的元素都是引用关系图中Root指向的元素,它们与白色集合中的元素没有任何引用关系。在做垃圾回收时,这个集合中的元素时不会被

    回收的,在很多系统的实现中,这个集合在系统初始化时是空的。

    • The Gray Set(灰色集合)。这个集合中的元素是被Root直接指向的。因为这些元素是Root直接指向的,所以它们在垃圾回收的时候会被移到黑色集合中。通常情况下,在系统初始化的时候,灰色集合中的元素是被Root直接指向的元素,其他所有元素都在白色集合中。 系统中所有的元素在同一时刻只能存在于一个集合中。回收算法是:

    +从灰色集合中选取一个元素

    +将这个元素移入黑色集合中,并且将它指向的所有白色集合中的元素都移入灰色集合中

    +重复上面的步骤,直到灰色集合为空

    此时,白色集合中的所有元素是被标记为没有任何变量引用它(直接引用或者间接引用)的元素的集合,它们是在垃圾回收时被清理掉的。 因为不能从Root直接可达的元素都在白色集合中,而且元素只能从白色集合移动到灰色集合,或者从灰色集合移动到黑色集合。这就保证了白色集合中的元素没有一个是黑色集 合中的元素指向的,所以在灰色集合为空时,我们可以安全地将白色集合中的元素删除。

    三色标记法的一个非常重要的优势就是可以在系统运行时执行。可以在分配内存对象时将它们标记,当白色集合的容量到达一定规模时,可以启动垃圾回收算法。 关于三色标记法的详细信息见维基百科

5.2 引用计数垃圾回收

基本思路是为每个对象加一个计数器,记录指向这个对象的引用数量。每次有一个新的引用指向这个对象,计数器加一;反之每次有一个指向这个对象引用被置空或者指向其他 对象,计数器减一。当计数器变为 0 的时候,自动删除该对象。 引用计数的优点是当某个对象的引用计数减为0时,它会马上被回收,不会对系统带来额外的中断,同时,因为此时该对象可能仍然在Cache中,所以它不会对Cache和虚拟内存 系统带来额外的开销。 但是它有不少缺点:一是循环引用计数的问题,有一些算法和方法专门来处理循环引用计数;二是为每个内存对象增加一个计数,会增大对象大小;三是,如果该内存对象 如果被多个线程或进程使用,那么它们同时增加和减少引用计数时要考虑互斥问题,这也会给系统带来不小的开销。

5.3 分代垃圾回收

通常情况下,又很多刚分配的临时对象,有可能马上就需要被回收;反之,那些长时间没有被回收的对象,它们的生命周期往往很长,对其频繁地回收没有任何意义。 分代垃圾回收器管理若干个生命周期不同的对象集合,刚分配的对象在生命周期较短的集合中,垃圾回收时优先回收生命周期较短的集合中的元素,然后把存活下来的元素移动 到生命周期较长的集合中。。。。以此类推。

5.4 对象使用类型分析

对于一些局部对象,没有必要在堆上分配它们,拥有垃圾回收功能的系统可以将局部对象在栈上分配,当函数调用返回时,这些临时对象会被自动释放。

6 参考

+ 维基百科

+ 知乎

Author: Cobbliu

Created: 2015-04-09 Thu 00:10

Emacs 24.4.1 (Org mode 8.2.10)

Validate

 
 

An Introduction to Garbage Collection(垃圾回收简介)的更多相关文章

  1. 【python进阶】Garbage collection垃圾回收1

    前言 GC垃圾回收在python中是很重要的一部分,同样我将分两次去讲解Garbage collection垃圾回收,此篇为Garbage collection垃圾回收第一篇,下面开始今天的说明~~~ ...

  2. 【python进阶】Garbage collection垃圾回收2

    前言 在上一篇文章[python进阶]Garbage collection垃圾回收1,我们讲述了Garbage collection(GC垃圾回收),画说Ruby与Python垃圾回收,Python中 ...

  3. JVM-5-GC(Garbage Collection) 垃圾回收机制

    GC(Garbage Collection)  垃圾回收机制   什么是垃圾回收机制 垃圾回收是一种动态存储管理技术,它自动地释放不再被程序引用的对象,按照特定的垃圾收集算法来实现资源自动回收的功能. ...

  4. Java GC系列(1):Java垃圾回收简介

    本文由 ImportNew - 好好先生 翻译自 javapapers. Java的内存分配与回收全部由JVM垃圾回收进程自动完成.与C语言不同,Java开发者不需要自己编写代码实现垃圾回收.这是Ja ...

  5. JavaScirpt 的垃圾(garbage collection)回收机制

    一.垃圾回收机制—GC Javascript具有自动垃圾回收机制(GC:Garbage Collecation),也就是说,执行环境会负责管理代码执行过程中使用的内存. 原理:垃圾收集器会定期(周期性 ...

  6. 【原创】GC/垃圾回收简介

    GC简介 1 GC机制 1.1 对象 从计算机的角度,装有数据的内存空间 1.2 作用 将内存垃圾的释放自动化 1.3 本质 将已经引用不到的对象视为死亡,将死亡的对象找出来并且作为垃圾进行回收 2 ...

  7. Java垃圾回收简介

    Java关键术语 JavaAPI:一系列帮助开发者创建Java应用程序的封装好的库. Java 开发工具包 (JDK):一系列工具帮助开发者创建Java应用程序.JDK包含工具编译.运行.打包.分发和 ...

  8. 【荐】PHP Session和Cookie,Session阻塞,Session垃圾回收,Redis共享Session,不推荐Memcached保存Session

    什么是 Session 在 web 应用开发中,Session 被称为会话.主要被用于保存某个访问者的数据. 由于 HTTP 无状态的特点,服务端是不会记住客户端的,对服务端来说,每一个请求都是全新的 ...

  9. php--session垃圾回收机制

    在PHP中,没有任何变量指向这个对象时,这个对象就成为垃圾.PHP会将其在内存中销毁:这是PHP的GC垃圾处理机制,防止内存溢出. GC的工作就是扫描所有的Session信息,用当前时间减去sessi ...

随机推荐

  1. AngularJs应用页面切换优化方案(转)

    目录[-] 前言 场景 使用resolve来提前请求数据 为页面加入切换动画 总结 葡萄城的一款尚在研发中的产品,对外名称暂定为X项目.其中使用了已经上市的wijmo中SpreadJS产品,另外,在研 ...

  2. Initializing a collection

    Before Java 1.7, only this one is permitted: ArrayList<String> a = new ArrayList<String> ...

  3. quartzScheduler_Worker-1] but has failed to stop it. This is very likely to create a memory leak解决

    01-Jul-2016 07:24:20.218 INFO [main] org.apache.catalina.startup.Catalina.start Server startup in 80 ...

  4. CoreOS实践(2)—在coreos上安装Kubernetes

    下载kubernetes sudo mkdir -p /opt/bin sudo wget https://storage.googleapis.com/kubernetes/binaries.tar ...

  5. Eclipse Maven to create Struts2 Project

    Follow the guide in this page: http://blog.csdn.net/topwqp/article/details/8882965 problem met : Des ...

  6. 【LeetCode】Power of Two

    问题描写叙述 Given an integer, write a function to determine if it is a power of two. 意:推断一个数是否是2的n次幂 算法思想 ...

  7. 管理windows防火墙

    1.导出防火墙规则 netsh advfirewall export "c:\advfirewall.wfw" 2.禁用防火墙 netsh firewall set opmode ...

  8. 用Zim替代org-mode?

    三年前我玩过Zim,当时还写了一篇<Zim - 普通人的Org-mode>,当时还说我还是会坚持使用emacs org-mode.但最近我又在考虑是不是回头用Zim来写博客文章.整理知识库 ...

  9. iOS开发——项目实战总结&Block使用注意点浅析

    Block使用注意点浅析 1.在使用block前需要对block指针做判空处理. 不判空直接使用,一旦指针为空直接产生崩溃. if (!self.isOnlyNet) { if (succBlock ...

  10. Kafka - SQL 引擎分享

    1.概述 大多数情况下,我们使用 Kafka 只是作为消息处理.在有些情况下,我们需要多次读取 Kafka 集群中的数据.当然,我们可以通过调用 Kafka 的 API 来完成,但是针对不同的业务需求 ...