zoukankan      html  css  js  c++  java
  • 内存分配以及合理使用

      1.内存分配

        a.栈分配

        b.对分配

      2.合理使用内存

      .内存分配

      系统新建一个线程的时候为这个线程分配一个1M(XP系统)大小的空间,栈采用先入后出的原则存储着数据和指令,当执行完毕后,栈内应该为空,.net 代码在被编译成IL二进制后,IL就是一系列指令和元数据说明等,这些指令就包含了栈的调用,对象的实例化等等,所以栈的空间回收是系统完成的。

      .net 中对象分配在堆中,并且由GC来回收不用的对象所占的空间。对Heap包含GCHeap和LoaderHeap,GCHeap表示的是能有GC回收的堆区域(堆栈都是逻辑上的),GCHeap包含小对象堆和大对象堆(Large object Heap>=85000字节).LoaderHeaper包含High-Frequency Heap、Low-Frequecy Heap、Stub Heap。

      GCHeap 小对象堆与大对象堆最大的不同时GC在回收空间的时候,会对小对象堆中的有效对象进行移动,使他们放在一起,对Loh不会移动空间。

      对小对象堆得回收过程是:GC首先认为所有的对象都是可以被回收的,然后通过算法计算哪些对象现在是有效地(在栈上去找存不存在这些空间的引用),把有效地对象给标记出来,然后回收不小对象的空间,进而就把这些有效对象移动到一起(这个过程中会计算对象的代数,最多三代,所以是“第三代对象|第二代对象|第一代对象”),在回收的时候会优先回收第一代对象),同时更新对象在栈中存储的引用地址为新地址,这样就有很多的内存空间并且是一次分配的(分配的时候有一个指向最后分配位置的指针,这样在分配新的对象的时候十分快速,当分配到最后堆空间不够分配的时候,CLR会启动GC回收,所以一般不提倡人为调用GC去回收内存,可能会扰乱CLR的正常工作)。

      对LOH,分配内存的时候会挨着随后一个分配,如果遇到不能分配的时候,启动GC ,Gc 回收空间,回收后不会移动对象地址(一定空间本身就是一个不小的消耗),后分配的对象会找一个能放下自己的空间。这样降低了内存利用。这是一个综合的考虑结果(鱼与熊掌不可兼得),“85000字节”也是一个经验值。

      内存条,内存条就是一个电路板,其中有很多的电路元件,晶体是其中的重要组成部分,用过电位(通断,有无电压)来表示0或者1,通过一个总线对外表示表示内存大小和内存地址,定位,通过改变晶体导电性,来达到记录(写)的目的。

    相应连接地址:

    1..NET内存管理、垃圾回收 http://www.cnblogs.com/riccc/archive/2009/09/01/dotnet-memory-management-and-garbage-collection.html

    2.你必须知道的.NET——内存分配 http://www.cnblogs.com/cheshui/archive/2012/09/29/2707910.html

    3.windows编程内存篇-实验讲解线程栈 http://hi.baidu.com/wesley0312/item/a3e02e9b7d36a48e59146124

    .net 在代码中的 对象回收和 内存利用

    1.正确的书写代码

      明确Finalize,Dispose,Close。

      代码中经常会开到对非托管对象的引用比如:Com组件,文件读写,数据库访问等等。

      GC回收对象的时候,如果该对象含有对非托管对象的引用,那么就回提示异常,GC不能结束掉对非托管对象的引用,需要我们手动来实现,为了保证GC回收对象的时候能结束掉对非托管引用对象,所以又了Finalize方法(析构函数编译后就编译成的Finalize方法)。Finalize,代码中不能显示重写Finalize方法(override方式),通过析构函数结束对非托管对象的引用

      因为GC会在一些情况下启动并回收对象,回收对象的的时间又可能不是我们想要的(比如:数据访问,假如我们也写了finalize方法,但是GC执行延迟,当我们第二次调用数据库连接对象的时候,GC还没有对该对象回收,并且长久的连接也消耗了资源),这时候我们需要另外一种方法,那就是IDisposable接口,这个接口.Net 类库中有定义,实现其中的Dispose方法,提供显示地结束掉对非托管代码的引用(不同的非托管资源结束引用方式可能不同,比如文件读取调用Closehandle方法(系统方法))。为了更好的的书写代码c#中有Using关键字,对象使用完后自动调用对象的Dispose方法,方便我们书写。

      对于文件读写和数据连接这样珍贵的非托管资源(具有独占性),我们一般是在想用的时候主动的打开引用,不用的时候就结束掉,有一个成对的“开-关”关系,所以习惯山我们会有一个Open和Close方法。

      所以,我们在写关于非托管的引用的时候,就最好把Finalize,Dispose,Close方法都合理的运用上。

    2.合理使用大对象

      大对象占用不少空间,有不利于GC的回收,怎么办呢?

      其一:使用小对象,把对象转换成小对象(比如:把大字符串使用过个小字符串来存储);

      其二:对对象弱引用:(WeakReference类):这个类的原理,比如 WeakReference wr = new WeakReference(A); A是一个大对象,占用不少空间,当使用弱引用后,当GC回收空间的时候即使在我们程序中没又被标记无效(A= null),A还是会被回收,从而节约了空间。后期再想使用怎么办了?先判断一下wr.Target是否为null,如果为null则表示被回收掉了,需要重新创建分配A,如果不为null,则表示还没有被GC回收掉,可以继续使用。这也是一个妥协的做法。

    相应连接地址:

    NET陷阱之五:奇怪的OutOfMemoryException——大对象堆引起的问题与对策  http://www.cnblogs.com/brucebi/archive/2013/04/16/3024136.html

     System.OutOfMemoryException: http://www.cnblogs.com/emanlee/archive/2009/06/25/1511198.html

     WeakReference 类http://msdn.microsoft.com/zh-cn/library/vstudio/system.weakreference.aspx

  • 相关阅读:
    使用WCF建立起Silverlight客户端与服务端的桥梁
    Silverlight WCF RIA服务(三十三)身份验证、角色、个性化 4
    陶哲轩实分析习题 12.1.3
    Asymptote 学习记录(6) 练习用模块roundedpath画出一个图
    使用Asymptote的循环功能画出绿叶阵
    使用Asymptote的循环功能画出绿叶阵
    度量空间的一个例子:离散度量空间
    练习: 使用Asymptote 画出字母R的轮廓曲线
    练习: 使用Asymptote 画出字母R的轮廓曲线
    陶哲轩实分析命题 11.10.7
  • 原文地址:https://www.cnblogs.com/beixing/p/3089934.html
Copyright © 2011-2022 走看看