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

前言


.Net下的GC全然攻克了开发人员跟踪内存使用以及控制释放内存的窘态。然而,你也许想要理解GC是怎么工作的。此系列文章中将会解释内存资源是怎么被合理分配及管理的,并包括很具体的内在算法描写叙述。

同一时候,还将讨论GC的内存清理流程及什么时清理。怎么样强制清理。

引子


为你的应用程序实现合理的资源管理是一件困难的,乏味的工作。这可能会把你的注意力从你当前正在解决的实际问题中转移到它身上。那么,假设有一个现有的机制为开发人员管理令人厌恶的内存管理。会不会是件快意人心的事?答案是YES!在.Net中。 有一种垃圾回收机制叫GC。

每个程序都须要使用一些计算机资源,如内存,显卡。网络,数据库等等。实际上,在一个面向对象的环境里,每个类型都代表着程序须要使用的资源。

假设要用到这些资源。则须要分配内存呈现这个类型。

以下是訪问这些资源的步骤:

  1. 分配内存给类型资源。

  2. 初始化内存和类型资源并使资源可用。

  3. 利用这些资源来訪问类型实例成员信息(按需反复)。
  4. 销毁并清理资源
  5. 释放内存

这看起来非常easy。但却是程序错误的根本来源。有多少次程序猿忘记释放闲置内存?有多少次程序猿试图訪问已经释放的内存?

这两种BUG是最糟糕的情况,由于它们导制的异常结果和发生时间是不可预測的。对于其他的BUG,当你看到程序执行错误时。直接修复即可了。这两种BUG最easy造成程序资源泄漏(浪费内存)和程序对象崩溃(不稳定)。并且还会促使应用程序在不可预知的时间产生不可预知的行为。当然了。有很多工具可用于跟踪监測这样的BUG。

当我们測试GC时,你应该知道它彻底攻克了开发人员跟踪内存使用及确定何时释放内存的问题。然而,垃圾回收GC并不了解不论什么关于类型在内存中代表的资源。

这意味着,GC不知道也不会去运行第四步:销毁并清理资源。在.net framework中,程序猿在方法Close,Dispose,Finalize中编写有关销毁清理资源的代码,兴许文章中会介绍。只是。GC可以决定什么时去自己主动调用这些方法。

有一些类型资源不须要清理。

如,Rectangle类型能够通过销毁它在内存中的left,right,width和height从而被彻底清理。还有一方面,一个文件类型资源或网络连接类型资源则须要很明白的清理代码来销毁。我将解释怎么适当地完毕这些任务。

如今,让我们了解一下内存是怎么分配的以及资源是怎么初始化的。

内存分配



.NET CLR将全部资源分配到托管堆上。这有点像C语言中的堆可是你不用去释放资源由于闲置资源在.NET中将被自己主动释放。如今就有一个问题了。托管堆是怎么知道一个对象什么时候将不再被程序使用?我将简介一下。

    
现今有非常多的GC算法。每个算法都针对某一特定环境进行调优,进而获得最好的性能。这篇文章着重于.NET CLR使用的GC算法。让我们从基本概念開始。

当一个线程初始化了,执行时将预定一块未使用的连续的地址空间。这块地址空间就是托管堆(深入浅出图解C#堆与栈
C# Heap(ing) VS Stack(ing)
)。堆中同一时候维护着一个指针,我们叫它下一个对象指针。

这个指针告诉我们下一个程序对象将被分配到堆中的什么位置。在程序初期,这个指针被设置到最基本(能够理解为第一位置)的内存地址。


程序使用newkeyword创建一个新对象。这个操作首先须要确定预定的地址空间是否足够存储新对象(内存空间是否足够)。假设足够。NextObjPtr(下一个对象指针)将指向堆中的此对象。对象构造函数被调用。最后返回对象内存地址。

托管堆(对堆与栈疑惑的朋友能够參考:深入浅出图解C#堆与栈):

(NextObjPtr:下一个对象指针)

此时,NextObjPtr将跳过此对象并指向下一个将要被存入的对象的内存地址。如上图,托管堆中有三个对象:A,B,C。下一个对象将会被放置到NextObjPtr指向的地址(即紧跟C之后)。

如今让我们看看C语言的堆怎么分配内存的。

在C语言堆中。为一个对象分配内存须要通过一个数据结构链表。一旦发现一个较大的块,则进行切割块。然后链表节点中的指针须要调整改动以保证全部数据原封不动(C语言不熟,原文:In a C-runtime heap, allocating memory for an object requires walking though a linked list of data structures. Once a large enough block is found, that block
has to be split, and pointers in the linked list nodes must be modified to keep everything intact. )。对.NET中的托管堆来讲。对象分配简单。仅仅须要向指针加入一个值。相比而言这是很快的。事实证明,在托管堆中分配一个对象差点儿像在线程栈里分配内存一样快!

到如今为止,听起来托管堆在速度上和实现简易性上要远远地优秀于C语言的堆。可是。要使托管堆拥有这些长处须要一个大前提:地址空间和存储空间是无限大的。当然,这有些不切实际,但托管堆必须使用一些机制原理来使这个所谓的如果成立。这个机制就是垃圾回收GC。让我们看看它是怎么工作的。

当一个程序使用new操作符创建一个新对象时,可能没有足够的地址空间来放置它。为了检測地址空间是否足够,托管堆会偿试把对象放到NextObjPtr位置,假设NextObjPtr移动到超过地址空间边界。那说明堆已满,GC则进行垃圾回收。

实际上,GC会在第0代(兴许文章会介绍GC中的代)被占满时进行垃圾回收。简单来说。GC中的代是GC实现的一种机制用来提高程序性能。原理上就是最新创建的对象属于GC的年轻一代,应用程序生命周期中较早创建的对象属于较老一代。把对象分成不同的代能够让GC知道要进行垃圾回收的特定代,而不是回收整个托管堆。

总结

本篇文章是为了让大家对垃圾回收GC和内存分配有一个初步的认识。不得不说了解内存分配对于一个程序猿是非常重要的。假设你想写高性能代码的话。尽管我们不必像使用C语言那样手工分配内存,但对内存分配茫然无知的程序猿多多少少会被歧视一点点的(仅仅是一点点。好吧。没有不论什么攻击性,请不要误解)。

下一篇文章将继续介绍垃圾回收GC的自己主动内存管理:内存算法。

翻译:http://msdn.microsoft.com/en-us/magazine/bb985010.aspx

垃圾回收GC:.Net自己主动内存管理 上(一)内存分配的更多相关文章

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

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

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

    垃圾回收GC:.Net自己主动内存管理 上(三)终结器 垃圾回收GC:.Net自己主动内存管理 上(一)内存分配 垃圾回收GC:.Net自己主动内存管理 上(二)内存算法 垃圾回收GC:.Net自己主 ...

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

    GC,Garbage Collect,中文意思就是垃圾回收,指的是系统中的内存的分配和回收管理.其对系统性能的影响是不可小觑的.今天就来说一下关于GC优化的东西,这里并不着重说概念和理论,主要说一些实 ...

  4. Java 垃圾回收(GC) 泛读

    Java 垃圾回收(GC) 泛读 文章地址:https://segmentfault.com/a/1190000008922319 0. 序言 带着问题去看待 垃圾回收(GC) 会比较好,一般来说主要 ...

  5. 类装饰器,元类,垃圾回收GC,内建属性、内建方法,集合,functools模块,常见模块

    '''''''''类装饰器'''class Test(): def __init__(self,func): print('---初始化---') print('func name is %s'%fu ...

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

    垃圾回收-GC 三个问题 哪些内存需要回收? 什么时候回收? 如何回收? YoungGC和FullGC: 新生代引发的GC叫YoungGC 老年代引发的GC叫FullGC FullGC会引起整个Jvm ...

  7. 这货到底还是不是垃圾?【垃圾回收GC算法JVM篇四】

    目录 1.判断对象是否存活的JVM两种计数算法 2.垃圾收集算法 3.垃圾回收算法小结 垃圾收集 Garbage Collection 通常被称为"GC", 在jvm 中,程序计数 ...

  8. 垃圾回收gc --翻译

    原文在https://developer.mozilla.org/en-US/docs/Web/JavaScript/Memory_Management.基本保持了平译,并在一些地方做了概念解释.(转 ...

  9. 垃圾回收GC

    ​ 每种语言都有自己的垃圾回收机制.接下来我们来讲一下python的垃圾回收机制. 小整数对象池:python对小整数的定义为[-5,257),这些整数对象是提前建立好的,不会被垃圾回收.单个字母也一 ...

随机推荐

  1. [LeetCode] Missing Number (A New Questions Added Today)

    Given an array containing n distinct numbers taken from 0, 1, 2, ..., n, find the one that is missin ...

  2. [转] Web前端优化之 图片篇

    原文链接: http://lunax.info/archives/3101.html Web 前端优化最佳实践第六部分面向 图片(Image),这部分目前有 4 条规则.在最近的 Velocity 2 ...

  3. vim 配置语法高亮 行号标示

    配置VIM主要是开启VIM的语法高亮和行号标示,因为默认在用户目录(~)下没有vimrc,所以需要先去复制一个,然后再编辑 cp /etc/vim/vimrc ~/.vimrc vim .vimrc ...

  4. kali 重置 mysql 密码

    You can recover MySQL database server password with following five easy steps. Step # 1: Stop the My ...

  5. 关于WordPress建站的原理二三事

    在写关于仿站文章详情页如何制作之前,我觉得有必要就一些原理性的问题,做一些说明.文章详情页的核心模块和首页有很多相似的地方,比如调用文章的标题.文章的内容.文章分类.作者等,实现起来都差不多,因此,了 ...

  6. LINQ标准查询操作符(五)

    十二.相等操作符 如果两个序列的对应元素相等且这两个序列具有相同数量的元素,则视这两个序列相等. SequenceEqual方法通过并行地枚举两个数据源并比较相应元素来判断两个序列是否相等.如果两个序 ...

  7. HDU 2040 亲和数 [补] 分类: ACM 2015-06-25 23:10 10人阅读 评论(0) 收藏

    今天和昨天都没有做题,昨天是因为复习太累后面忘了,今天也是上午考毛概,下午又忙着复习计算机图形学,晚上也是忘了结果打了暗黑3,把暗黑3 打通关了,以后都不会玩太多游戏了,争取明天做3题把题目补上,拖越 ...

  8. HD2058The sum problem

    The sum problem Time Limit: 5000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Tot ...

  9. c语言指针详解(转载)

    转自(http://blog.csdn.net/ad_ad_ad/article/details/1522145) 指针是C语言中广泛使用的一种数据类型. 运用指针编程是C语言最主要的风格之一.利用指 ...

  10. labview 中的一些简写全称

    MAX:Measurement & Automation Explorer 测量自动化管理器 :可用于配置DAQ通道名称,VISA资源名称和IVI逻辑名称. DAQ: Device Data ...