CLR内存管理简介

使用c#语言编写应用程序的一个好处就是不需要担心内存的管理,垃圾回收器(GC)会自动执行所有的内存清理工作。但是,了解内存的管理过程对于提高程序的性能还是有必要的,下面就简单介绍一下CLR的内存管理过程:

Windows使用虚拟寻址系统来管理内存,该系统把程序实际可用的内存地址映射到硬件内存中的实际地址上,带来的结果是32位处理器上的每个进程都可以使用4GB的内存,无论计算机上实际有多少硬盘空间(如果是64位处理器,可用内存会更大)。这个4GB的内存包含了程序的所有部分,可执行代码、要加载的DLL,程序运行使用的所有变量内容。这4GB的内容空间,就成为虚拟地址空间或者虚拟内存。CLR的内存管理的分配,就是在这个空间上进行的。

值类型的内存分配:

在虚拟内存空间中,有一个区域成为栈,栈用来存储不是对象成员的值类型数据

int a=10;
//do something
{
 int b=5;
}

如上所示,我们声明变量的过程,其实就是分配内存的过程。在诸如:C#、VB、C++和java中,编译器负责把人们可以理解的变量名转换为处理器可以理解的内存地址,比如上面所提到的a和b。为了理解栈的工作原理,需要了解变量作用域的概念。变量a在变量b之前进入作用域,b就会首先超出作用域。所以,我们可以说,b的生命周期完全包含在a的生命周期内。也就是说,在释放变量时,其顺序总是与给他们分配内存时的顺序相反,这就是栈的工作方式。

那么,C#程序是如何从虚拟地址空间中找到可用的空闲内存区域的呢?实际上是通过操作系统维护的一个变量,我们称之为栈指针,它总是存储着栈保留内存块中下一个空闲存储单元的地址。程序第一次运行时,栈指针指向栈内存的内存块末尾。栈的填充是自上而下的,也就是从高位内存地址向低位内存地址填充。当数据入栈后,栈指针随之进行调整,始终指向下一个可用的空闲存储区域。如上所示,当变量b首先超出作用域后,程序就不需要这个变量了,因为栈的存储机制中,变量的生命周期总是嵌套的。想要删除变量b,应该给栈指针的值递增4,因为存储一个int型变量需要4个字节的空间。之前存储变量b的空间重新变为空闲的存储单元。

如果遇到 int c,d; 这样的代码,则两个变量进入作用域的顺序就是不确定的,他们同时声明,同时超出作用域。但编译器会确保先放到内存中的变量后删除,这样就与栈的机制一致了。

引用类型的内存分配:

尽管栈的性能非常高,但它不是对所有的变量都适用的。变量的生命周期必须嵌套,这种限制有些情况下是很不方便的。我们有时间需要内存存储一些数据,并且在很长一段时间内数据仍然是可用的。此时我们就要涉及到另一种常见的托管类型——引用类型。我们也要使用虚拟内存中的另一个区域——托管堆。

先看如下代码:

Person person;
person=New Person;

首先声明了一个Person类型的引用变量person,此时内存中进行的操作是:在栈上给这个引用变量分配4个字节的空间,这个空间只用来存储实际Person对象的地址,而不是实际的对象数据。第二行代码完成了以下操作:首先,它分配托管堆上的内存,以存储真正的Person对象,然后把对象数据所在内存块的地址赋值给变量person。只要程序中还有变量在引用Person对象,它就不会被垃圾回收器回收。这样,实际上是给了我们控制变量生存周期的一种途径,只要我们保持对数据的引用,该数据就肯定存在于堆上。

垃圾回收器:

CLR会利用垃圾回收器删除不再引用的所有对象。在完成删除操作后,相应的内存空间会被释放。如果垃圾回收器仅仅做这些事情,那么再有新的对象需要分配内存空间时就有可能非常困难。因为释放的内存空间和已用的空间是混合在一起的。CLR必须搜索整个堆,才能找到合适大小的内存区域。但是垃圾回收器不会让堆保持这种状态,当它清理完所有需要释放的对象时,它会把已用的对象移动到堆的端部,再次形成一个连续可用的空闲内存区域。堆又可以像栈那样确定在什么地方存储数据了。当然,在移动对象时,所有的引用都要用新的地址来更新,这必然会造成额外的性能损失。

垃圾回收器在CLR需要它时运行,我们也可以调用System.GC.Collect()方法,强制垃圾回收器运行。但是,这种情况适用的场景很少,例如,代码中刚好有大量的对象取消引用,这时就适合调用GC。但是,垃圾回收器不能保证在一次的执行中,所有未引用的对象都从堆中删除。

垃圾回收提高性能的另一个架构处理是处理堆上较大的对象的方式。较大的对象有自己的托管堆,成为大对象堆。使用大于85,000个字节的对象时,它们就会被放到这个特殊的堆上,而不是主堆上。原因是在堆上压缩大的对象是比较昂贵的,而驻留在大对象堆上的数据是不需要执行前面提到的压缩过程。

当然,我在这里仅仅介绍了托管资源的管理,关于非托管资源的释放,我会在下篇文章中介绍。

转载于:https://www.cnblogs.com/yonghuisoft/archive/2013/01/19/CLRModel.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值