团队项目中用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. 使用MySQL Migration Toolkit快速将Oracle数据导入MySQL[转]

    使用MySQL Migration Toolkit快速将Oracle数据导入MySQL上来先说点废话本人最近在学习一些数据库方面的知识,之前接触过Oracle和MySQL,最近又很流行MongoDB非 ...

  2. eclipse android logcat 只显示自己应用程序信息的设置方法

    1 elcipse 中往往会在logcat中显示 all message ,而这里面的信息太多,根本没有办法进行区分.如图: 2 我们想显示自己项目的 logcat .下面开始设置. 3 首先点击上面 ...

  3. Android开发(二十九)——layout_weight的含义

    首先声明只有在Linearlayout中,该属性才有效.之所以android:layout_weight会引起争议,是因为在设置该属性的同时,设置android:layout_width为wrap_c ...

  4. No module named flask.ext.sqlalchemy.SQLALchemy

    在学习<OReilly.Flask.Web.Development>的时候,按照书的例子到了数据库那一章,在运行python hello.py shell的时候出现了“ImportErro ...

  5. 【Linux】——sleep无法正常休眠

    最近在开发项目的时候遇到一个问题,当使用 sleep(2) 的时候,程序居然没有按照指定的时间去休眠,但是连续执行两次 sleep(2) 的时候,程序可以正常的休眠 2 秒.真是见鬼了.最后查看了以下 ...

  6. 【Cocos2d-Js基础教学(7)界面UI更新方法(会用到第三方类库)】

    我们游戏中会遇到很多UI更新的时候,大部分时候我们会remove该节点,再重新绘制的方法来进行UI更新. 但是这种更新效率并不高,这里我推荐大家一个第三方的库,来通过注册更新的方式来对UI进行更新管理 ...

  7. 关于DDD的 认识

    tks: 第一篇: 领域驱动设计系列(1)通过现实例子显示领域驱动设计的威力 第二篇: 领域驱动设计系列(2)浅析VO.DTO.DO.PO的概念.区别和用处 第三篇: 领域驱动设计系列(3)有选择性的 ...

  8. 【Spark】jupyter notebook

    iPython 和 Jupter Notebook 都支持spark ,调用方式如下: PYSPARK_DRIVER_PYTHON=ipython ./bin/pysparkPYSPARK_DRIVE ...

  9. 在SpringMVC中获取request对象的几种方式

    1.最简单的方式(注解法) @Autowired private HttpServletRequest request; 2.最麻烦的方法 a. 在web.xml中配置一个监听 <listene ...

  10. [论文笔记] Methodologies for Data Quality Assessment and Improvement (ACM Comput.Surv, 2009) (1)

    Carlo Batini, Cinzia Cappiello, Chiara Francalanci, and Andrea Maurino. 2009. Methodologies for data ...