zoukankan      html  css  js  c++  java
  • .net GC内存管理

    背景

    以前公司的代码中用到了Ninject,由于对ninject不太了解,所以看了源码中的单元测试代码,看到了有关gc的操作。
    所以整理一份文章,以When(何时回收)--What(回收什么)--How(如何回收)的方式简洁的介绍下.net GC内存管理垃圾回收。

    https://github.com/ninject/Ninject/blob/master/src/Ninject.Test/Integration/TransientScopeTests.cs

    When 何时回收

    1)当Gen 0 heap内存达到最大阀值,则触发0代GC,0代GC后Gen 0中幸存的对象进入Gen1;
    当Gen 1 heap的内存达到最大阀值,则触发1代GC,1代GC将Gen 0 heap和Gen 1 heap一起进行回收,幸存的对象进入Gen2;
    当Gen 2 heap内存达到最大阀值,2代GC时将Gen 0 heap、Gen 1 heap和Gen 2 heap一起回收;
    Ps:Gen 0和Gen 1比较小,总和保持在16M左右;Gen2的大小由应用程序确定,可能达到几G,因此0代和1代GC的成本非常低,2代GC称为full GC,通常成本很高。 2代、1代和0代GC的频率应当大致为1:10:100。
    2)手动调用GC.Collect(); //实现代码中不推荐用
    3)卸载AppDomian

     扩展知识 Generation 分代

    托管堆内存分代算法具备一定统计学基础,对GC的性能改善效果比较明显。将对象按照生命周期分成新的、老的,根据统计分布规律所反映的结果;
    对新、老区域采用不同的回收策略和算法,加强对新区域的回收处理力度,争取在较短时间间隔、较小的内存区域内,以较低成本将大量新创建但不再使用的局部对象及时回收掉。分代算法的假设前提条件:
      1、大量新创建的对象生命周期都比较短,而较老的对象生命周期会更长;
      2、对部分内存进行回收比基于全部内存的回收操作要快;
      3、新创建的对象之间关联程度通常较强。heap分配的对象是连续的,关联度较强有利于提高CPU cache的命中率,.NET将heap分成3个代龄区域: Gen 0、Gen 1、Gen 2如右图;
    Ps:0,1,2代为小对象内存区,如果大小超过85000字节,会被分到大对象内存区,在回收2代是回去回收大对象内存区, 并不会在回收时清理碎片,影响性能。

    What 回收哪些对象

    托管资源:
    1)引用类型对象没有重写过Finalize方法(没有析构函数)
    当托管堆中的对象没有被栈中的任何地址指向,那么对象没有被标记为Reachable,从而在GC Roots中已经搜索不到的;
    2)引用类型对象没有重写过Finalize方法(有析构函数)
    当托管堆中的对象没有被栈中的任何地址指向,那么对象没有被标记为Reachable,在Finalization Queue中找不到任何地址指向,然后在Freachable Queue中没有复活,找不到任何地址指向,在GC Roots中已经搜索不到的;
    3)弱引用:当被弱引用对象引用的对象已经被回收时,GC会在这次回收中回收它。(高速缓存)
    非托管资源:(非GC直接回收)
    1)当引用类型对象重写过Finalize方法时(有析构函数),且用户没有手动去调用非托管对象的Dispose去手动释放非托管资源的情况下,用户可以在析构函数中通过调用非托管对象的Dispose方法,作为非托管对象的释放的保底做法。当引用对象被GC回收时,GC会去调引用对象的Finalize方法(析构函数),从而非托管对象的Dispose会被调用去释放非托管资源。
    Ps:资源均是调用Object.Finalize()释放的,但无法手动直接调用,可以等GC调用,或者通过Dispose间接调用。

     扩展知识

    托管堆
    引用类型 (实例本身)

    值类型(引用对象的地址也存在栈中)
    非托管堆
    ApplicationContext, Brush, Component, ComponentDesigner, Container, Context, Cursor, FileStream, Font, Icon, Image, Matrix, Object, OdbcDataReader, OleDBDataReader, Pen, Regex, Socket, StreamWriter, Timer, Tooltip, 文件句柄, GDI资源, 数据库连接等等资源.
    GC Roots
    可以理解为CLR在heap之外可以找到的各种入口点,并存在多个gc roots.
    https://stackoverflow.com/questions/8458886/what-is-a-rooted-reference
    https://blogs.msdn.microsoft.com/abhinaba/2009/01/30/back-to-basics-mark-and-sweep-garbage-collection/

       

      

    How 如何回收 

     

      

     扩展知识

    比较常见的gc回收算法
    1) Mark Sweep (.net java) : https://blogs.msdn.microsoft.com/abhinaba/2009/01/30/back-to-basics-mark-and-sweep-garbage-collection/
    2) Reference Counting : https://secweb.cs.odu.edu/~zeil/cs361/web/website/Lectures/garbageCollection/pages/referenceCounting.html
    3) Copy Collection : Garbage collection is performed by copying live objects from one semispace (the from-space) to the other (the to-space), which then becomes the new heap. The entire old heap is then discarded in one piece

    非托管资源的推荐清理方式(引用对象下有非托管资源)

    1) 手动调用引用对象的Dispose();
    2) 在析构函数中调用非托管资源实现的Dispose()做为保底;

      

     参考资料

     《CLR via c#》

  • 相关阅读:
    不开心的事
    git push 时 error: RPC failed; HTTP 400 curl 55 Send failure: Connection was reset 问题
    Java多线程相关
    angularJS 级联下拉框
    leetcode260 Single Number III
    -2147483648的绝对值
    git 提交信息模板
    rabbitmq at com.rabbitmq.client.impl.Frame.readFrom(Frame.java:91) ~[amqp-client-5.4.3.jar:5.4.3] 错误
    Unity 切换场景的注意点
    Java位运算
  • 原文地址:https://www.cnblogs.com/willardzmh/p/13381344.html
Copyright © 2011-2022 走看看