你必须知道的.NET读书笔记分享——(3)内存及性能相关

 1、CLR管理内存的区域

  线程的堆栈:用于分配值类型实例,主要受操作系统管理,不受垃圾收集器的控制,当值类型实例所在方法结束后将自动释放资源。栈的执行效率高,但存储容量有限;

  GC堆:分配小的对象实例,当有内存分配或者回收时,垃圾收集器可能会对GC堆进行压缩;

  LOH(Large Object Heap)堆:用于分配大对象实例。如果引用类型对象的实例大小超过85000个字节时,则将被被分配到LOH上。

2、何时垃圾回收

  · 内存不足溢出时;

  · 调用GC.Collect方法强制执行垃圾回收;

  · windows报告内存不足时,CLR将强制执行垃圾回收;

  · CLR卸载AppDomain时,GC将对所有代龄对象执行垃圾回收;

  · 一个对象没有被任何其他对象引用时。

  

  代龄:代龄越小,表示对象越新,通常情况下其生命周期也最短,因此垃圾收集器总是首先收集第0代的不可达对象内存。随着对象的不存创建,垃圾收集器再次启动时只会检查0代对象,并回收0代垃圾对象,而1代对象由于未达到预定的1代容量阈值,将不会进行垃圾回收,从而有效的提高了垃圾收集的效率。

3、Finalize模式

  · 在System.Object中Finalize方法被实现为一个受保护的虚方法,GC要求任何需要释放非托管资源的类型都要重写该方法,如果一个类型及其父类均未重写Sytem.Object的Finalize方法,则GC认为该类型及其父类不需要执行终止化操作,当对象变成不可达对象时,将不会执行任何资源清理操作;

  · GC.SuppressFinalize方法可以免除终结;

  · C#中无法显示重写Finalize方法,只能通过析构函数来实现;

  弊端:

  · 终止化操作的时间无法控制,执行顺序也不能保证;

  · 损伤性能:调用Finalize方法时将清理包括父类的所有资源;

  · 代龄提升,增加内存压力;

  · 某些情况下Finalize方法可能不被执行。

4、Dispose模式

  .NET提供的一种显示清理对象资源你的约定方式,用于在.NET中释放对象封装的非托管资源,因为非托管资源不受GC限制,对象必须调用自己的Dispose方法来释放。

  最佳资源清理策略——同时实现Finalize方法和Dispose方法,Dispose方法克服了Finalize方法的弊端,Finalize方法又保证了没有显示调用Dispose方法时也自行回收使用的所有资源。

  · Finalize方法和Dispose方法都只能清理非托管资源,释放内存的工作还是GC负责。

5、托管资源和非托管资源

  

  最常见的一类非托管资源就是包装操作系统资源的对象,例如文件,窗口或网络连接,对于这类资源虽然垃圾回收器可以跟踪封装非托管资源的对象的生存期,但它不了解具体如何清理这些资源。几种常见的非托管资源:ApplicationContext,Brush,Component,ComponentDesigner,Container,Context,Cursor,FileStream,Font,Icon,Image,Matrix,Object,OdbcDataReader,OleDBDataReader,Pen,Regex,Socket,StreamWriter,Timer,Tooltip 等。

  

  默认情况下,Finalize 方法不执行任何操作。如果您要让垃圾回收器在回收对象的内存之前对对象执行清理操作,您必须在类中重写 Finalize 方法。在C#中,可以通过析构函数自动生成 Finalize 方法和对基类的 Finalize 方法的调用。  

1 例如:
2  ~MyClass()
3 {
4 // Perform some cleanup operations here.
5  }
6 该代码隐式翻译为下面的代码。
7 protected override void Finalize()
8 {
9 try
10 {
11 // Perform some cleanup operations here.
12 }
13 finally
14 {
15 base.Finalize();
16 }
17 }
18

   

6、性能相关

  · 选择合适的垃圾收集器:工作站GC(应用于单处理器系统)、服务器GC(为多处理的服务器系统设计);

  · 尽可能地用using来执行资源清理;

  · 推荐使用泛型集合来代替非泛型集合;

  · 初始化时最好为集合对象指定大小;

  · 特定类型的Array性能优于ArrayList(ArrayList只接受Object类型的参数,添加时会发生装箱与拆箱操作);

  · 使用StringBuilder进行复杂字符串操作;

  · 使用String.Compare方法进行字符串比较操作;

  · 使用foreach遍历数组优于for(foreach能够迭代多维数组,自动检测数组的上下限,并自动适应不同的类型转换);

  · 捕获异常时尽量指定具体的异常类型;

作者:Rocky翔
出处:http://www.cnblogs.com/RockyMyx/
本文版权归作者和博客园共有,欢迎转载,但请在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
posted @ 2010-10-18 12:30  RockyXiang  阅读(236)  评论(0编辑  收藏  举报