.NET垃圾回收(GC)原理

转载:http://mp.weixin.qq.com/s?__biz=MjM5MDI5MjAyMA==&mid=203643791&idx=1&sn=f65d23bcf7e270d1e69ac9fc5f648581&scene=1#rd

作为.NET进阶内容的一部分,垃圾回收器(简称GC)是必须了解的内容。本着“通俗易懂”的原则,本文将解释CLR中垃圾回收器的工作原理。

基础知识

托管堆(Managed Heap)

先来看MSDN的解释:初始化新进程时,运行时会为进程保留一个连续的地址空间区域。这个保留的地址空间被称为托管堆。

“托管堆也是堆”,为什么这样说呢?这么说是希望大家不要被“术语”迷惑,这个知识点的前提是“值类型和引用类型的区别”。这里假设读者已经知道“值类型存储在栈中,引用类型存储在堆中。(引用类型的引用存储在栈中)”这一重要概念。所以,根据这个理论,除值类型外,CLR要求所有资源都从托管堆分配。

托管堆维护着一个指针,这里命名为NextObjPtr,它指向下一个对象在堆中的分配位置。

CPU寄存器(CPU Register)

这个是计算机基础知识,这里复习一下,有助于对下面“根”概念的理解。

CPU寄存器是CPU自己的”临时存储器”,比内存的存取还快。按与CPU远近来分,离得最近的是寄存器,然后缓存(计算机一、二、三级缓存),最后内存。

根(Roots)

类中定义的任何静态字段,方法的参数,局部变量(仅限引用类型变量)等都是根,另外cpu寄存器中的对象指针也是根。根是CLR在堆之外可以找到的各种入口点。

对象可达与不可达(Objects reachable and unreachable)

如果一个根引用了堆中的一个对象,则该对象为“可达”,否则即是“不可达”。

垃圾回收的原因

从计算机组成的角度来讲,所有的程序都是要驻留在内存中运行的。而内存是一个限制因素(大小)。除此之外,托管堆也有大小限制。如果托管堆没有大小限制,那C#的执行速度要优于c了(托管堆的结构让它有比c运行时堆更快的对象分配速度)。因为地址空间和存储的限制因素,托管堆要通过垃圾回收机制,来维持它的正常运作,保证对象的分配,不会“内存溢出”。

垃圾回收的基本原理

回收分为两个阶段: 标记 –> 压缩

标记的过程,其实就是判断对象是否可达的过程。当所有的根都检查完毕后,堆中将包含可达(已标记)与不可达(未标记)对象。

标记完成后,进入压缩阶段。在这个阶段中,垃圾回收器线性的遍历堆,以寻找不可达对象的连续内存块。并把可达对象移动到这里以压缩堆。这个过程有点类似于磁盘空间的碎片整理。

如上图所示,绿色框表示可达对象,黄色框为不可达对象。不可达对象清除后,移动可达对象实现内存压缩(变得更紧凑)。

压缩之后,“指向这些对象的指针”的变量和CPU寄存器现在都会失效,垃圾回收器必须重新访问所有根,并修改它们来指向对象的新内存位置。这会造成显著的性能损失。这个损失也是托管堆的主要缺点。

基于以上特点,垃圾回收引发的回收算法也是一项研究课题。因为如果真等到托管堆满才开始执行垃圾回收,那就真的太“慢”了。

垃圾回收算法 – 分代(Generation)算法

代是CLR垃圾回收器采用的一种机制,它唯一的目的就是提升应用程序的性能。分代回收,速度显然快于回收整个堆。

CLR托管堆支持3代:第0代,第1代,第2代。第0代的空间约为256KB,第1代约为2M,第2代约为10M。新构造的对象会被分配到第0代,

如上图所示,当第0代的空间满时,垃圾回收器启动回收,不可达对象(上图C、E)会被回收,存活的对象被归为第1代。

当第0代空间已满,第1代也开始有很多不可达对象以至空间将满时,这时两代垃圾都将被回收。存活下来的对象(可达对象),第0代升为第1代,第1代升为第2代。

实际CLR的代回收机制更加“智能”,如果新创建的对象生存周期很短,第0代垃圾也会立刻被垃圾回收器回收(不用等空间分配满)。另外,如果回收了第0代,发现还有很多对象“可达”,

并没有释放多少内存,就会增大第0代的预算至512KB,回收效果就会转变为:垃圾回收的次数将减少,但每次都会回收大量的内存。如果还没有释放多少内存,垃圾回收器将执行

完全回收(3代),如果还是不够,则会抛出“内存溢出”异常。

也就是说,垃圾回收器会根据回收内存的大小,动态的调整每一代的分配空间预算!达到自动优化!

总结

垃圾回收背后有这样一个基本的观念:编程语言(大多数的)似乎总能访问无限的内存。而开发者可以一直分配、分配再分配——像魔法一样,取之不尽用之不竭。

.NET垃圾回收器的基本工作原理是:通过最基本的标记清除原理,清除不可达对象;再像磁盘碎片整理一样压缩、整理可用内存;最后通过分代算法实现性能最优化。

时间: 2024-11-02 15:32:55

.NET垃圾回收(GC)原理的相关文章

垃圾回收GC:.Net自动内存管理 上(一)内存分配

垃圾回收GC:.Net自动内存管理 上(一)内存分配 前言 .Net下的GC完全解决了开发者跟踪内存使用以及控制释放内存的窘态.然而,你或许想要理解GC是怎么工作的.此系列文章中将会解释内存资源是怎么被合理分配及管理的,并包含非常详细的内在算法描述.同时,还将讨论GC的内存清理流程及什么时清理,怎么样强制清理. 引子 为你的应用程序实现合理的资源管理是一件困难的,乏味的工作.这可能会把你的注意力从你当前正在解决的实际问题中转移到它身上.那么,如果有一个现有的机制为开发者管理令人厌恶的内存管理,会

从C#垃圾回收(GC)机制中挖掘性能优化方案

GC,Garbage Collect,中文意思就是垃圾回收,指的是系统中的内存的分配和回收管理.其对系统性能的影响是不可小觑的.今天就来说一下关于GC优化的东西,这里并不着重说概念和理论,主要说一些实用的东西.关于概念和理论这里只做简单说明,具体的大家可以看微软官方文档. 一.什么是GC                                                                                              GC如其名,就是垃圾收集

Java 垃圾回收(GC) 泛读

Java 垃圾回收(GC) 泛读 文章地址:https://segmentfault.com/a/1190000008922319 0. 序言 带着问题去看待 垃圾回收(GC) 会比较好,一般来说主要的疑惑在于这么几点: 为什么需要 GC ? 虚拟机(JVM) 与 垃圾回收(GC) 的关系? GC 的原理有哪些? 哪些 对象容易被 GC ? 等等 带着这些问题往下看: 1. 为什么需要 GC ? GC: 是Garbage Collection 的英文缩略,垃圾收集的意思. 为什么需要 GC?主要

垃圾回收GC:.Net自己主动内存管理 上(一)内存分配

垃圾回收GC:.Net自己主动内存管理 上(一)内存分配 垃圾回收GC:.Net自己主动内存管理 上(一)内存分配 垃圾回收GC:.Net自己主动内存管理 上(二)内存算法 垃圾回收GC:.Net自己主动内存管理 上(三)终结器 前言 .Net下的GC全然攻克了开发人员跟踪内存使用以及控制释放内存的窘态.然而,你也许想要理解GC是怎么工作的.此系列文章中将会解释内存资源是怎么被合理分配及管理的,并包括很具体的内在算法描写叙述. 同一时候,还将讨论GC的内存清理流程及什么时清理.怎么样强制清理.

JVM 及 垃圾回收机制原理

JVM Java 虚拟机 Java 虚拟机(Java virtual machine,JVM)是运行 Java 程序必不可少的机制.JVM实现了Java语言最重要的特征:即平台无关性.原理:编译后的 Java 程序指令并不直接在硬件系统的 CPU 上执行,而是由 JVM 执行.JVM屏蔽了与具体平台相关的信息,使Java语言编译程序只需要生成在JVM上运行的目标字节码(.class),就可以在多种平台上不加修改地运行.Java 虚拟机在执行字节码时,把字节码解释成具体平台上的机器指令执行.因此实

性能测试三十五:jvm垃圾回收-GC

垃圾回收-GC 三个问题 哪些内存需要回收? 什么时候回收? 如何回收? YoungGC和FullGC: 新生代引发的GC叫YoungGC 老年代引发的GC叫FullGC FullGC会引起整个Jvm的用户线程暂停,待垃圾回收完毕后,才继续运行 引用的定义:如果reference类型的数据中存储的数值代表的是另外一块内存的起始地址,就称这块内存代表一个引用 对象存活状态: 确定对象"存活"还是"死去":以下两种算法原理都一样,就是看当前这个对象,是否有引用正在指向它

垃圾回收GC:.Net自动内存管理 上(三)终结器

垃圾回收GC:.Net自动内存管理 上(三)终结器 垃圾回收GC:.Net自动内存管理 上(一)内存分配 垃圾回收GC:.Net自动内存管理 上(二)内存算法 垃圾回收GC:.Net自动内存管理 上(三)终结器 前言 .Net下的GC完全解决了开发者跟踪内存使用以及控制释放内存的窘态.然而,你或午想要理解GC是怎么工作的.此系列文章中将会解释内存资源是怎么被合理分配及管理的,并包含非常详细的内在算法描述.同时,还将讨论GC的内存清理流程及什么时清理,怎么样强制清理. 终结器 GC提供了另外一个能

垃圾回收的原理

groot.createElement = function (html, id) { groot.dynamic[id] = id; return $(html).append("<input type='hidden' id=\"" + id + "\">") } 从上面得代码可以看出 函数在html代码片段的后面加了隐藏的input 并在 groot.dynamic加了添加了一个属性 function _collection()

垃圾回收GC:.Net自己主动内存管理 上(二)内存算法

垃圾回收GC:.Net自己主动内存管理 上(二)内存算法 垃圾回收GC:.Net自己主动内存管理 上(一)内存分配 垃圾回收GC:.Net自己主动内存管理 上(二)内存算法 垃圾回收GC:.Net自己主动内存管理 上(三)终结器 前言 .Net下的GC全然攻克了开发人员跟踪内存使用以及控制释放内存的窘态.然而,你或午想要理解GC是怎么工作的.此系列文章中将会解释内存资源是怎么被合理分配及管理的,并包括很具体的内在算法描写叙述.同一时候.还将讨论GC的内存清理流程及什么时清理,怎么样强制清理. 内