引言

GC 作为CLR的垃圾回收器,让程序员可以把更多的关注度放在业务上而不是垃圾回收(内存回收)上。其实很多语言也有类似的东东,

如Java也有JIT 等等

GC基本概念

  • 垃圾回收机制的算法有好多种,GC为Mark-Sweep算法。
  • GC中分为三代,来优化管理不同生命周期的对象。
  • 大部分的对象在Gen0就死掉了。
  • Gen0 和Gen 1 又叫作ephemeral generations (短命代,个人翻译意见 )
  • 大于85,000bytes的对象会被直接分配到Large object heap上,且在Gen2回收时才会被回收。

GC回收时机

  1. 系统内存不足
  2. Gen0 没有足够的空间需要申请新的空间(应该是segment)
  3. 手动条用GC.Collect()

GC步骤

当进行一次垃圾回收操作时,会分三个步骤进行:
1. 先假设所有对象都是垃圾;
2. 标记出正在使用的对象; (会先找GC Roots,然后遍历GC Heap上的每个对象,生成一个对象List)
标记依据:
     a. 被变量引用的对象,仍然在作用域中。
     比如某个类中的某个方法,方法执行了一半,如果此时发生垃圾回收,那么方法块中的变量都在作用域中,那么它们都会被标记为正在使用。
     b. 被另一个对象引用的对象,仍在使用中。
3. 压缩:释放第二步中未标记的对象(不再使用,即“垃圾”)并将使用中的对象转移到连续的内存块中。
只要垃圾回收器释放了能释放的对象,它就会压缩剩余的对象,把它们都移回堆的端部,再一次形成一个连续的块。(这里其实有个更新引用或者说指针的操作)

GC处理Finalizalbe对象工作原理

上图假设是新创建对象为Gen0 代的且为Finalizable的对象,首次就会被回收(如局部的且<85,000bytes的对象)。

实现 Finalize 方法或析构函数对性能可能会有负面影响,因此应避免不必要地使用它们。用 Finalize 方法回收对象使用的内存需要至少两次垃圾回收。当垃圾回收器执行回收时,它只回收没有终结器的不可访问对象的内存。这时,它不能回收具有终结器的不可访问对象。它改为将这些对象的项从终止队列中移除并将它们放置在标为准备终止的对象列表中。该列表中的项指向托管堆中准备被调用其终止代码的对象。垃圾回收器为此列表中的对象调用 Finalize 方法,然后,将这些项从列表中移除。后来的垃圾回收将确定终止的对象确实是垃圾,因为标为准备终止对象的列表中的项不再指向它们。在后来的垃圾回收中,实际上回收了对象的内存。

GC分类

从工作模式角度来看:

两大类:WorkStation GC Server GC

分类依据:

WorkStation GC 是默认的工作方式,如果你是单处理器的机器,那么这是你唯一的选择,并且及时你配置了Concurrent选项为True,也不会生效。

Server GC 在多处理器的机器上才会出现,且默认出现在Aps.net寄存服务中。他会为每个处理器都创建一个GC Heap,并且会并行执行回收操作。该模式的GC可以最大化吞吐量和较好的收缩性(4处理器+)

<configuration>
  <runtime>
    <gcServer enabled="true" />
  </runtime>
</configuration>

可以通过以上配置方式或者通过native code 类指定GC 工作模式

HRESULT CorBindToRuntimeEx( LPWSTR pwszVersion,
  LPWSTR pwszBuildFlavor, // use “svr” for server mode,
  // “wks” or NULL for workstation
  DWORD flags,
  REFCLSID rclsid,
  REFIID riid,
  LPVOID* ppv );

下表为GC为GC heap向系统申请时的基本单位Segment的默认值,注意是默认值,这些值会随着程序的实际执行情况,GC动态调整。这里了解下即可,另外正是由于有segment的概念所以回出现内存碎片的问题,所以GC在垃圾回收过程中会进行内存整理,以减少内存碎片,提高内存使用率。

 

32-bit

64-bit

Workstation GC

16 MB

256 MB

Server GC

64 MB

4 GB

Server GC with > 4 logical CPUs

32 MB

2 GB

Server GC with > 8 logical CPUs

16 MB

1 GB

从工作方式,工作侧重点和实现上来看:

两类:Foreground GC,Concurrent GC | BackGround GC(侧重于Gen2 GC性能优化,正常情况Gen0 ,Gen1的速度都比较快)

Foreground GC工作的时候绝对是.net 程序要向系统申请分配Gc Heap空间啦,所以它的优先级最高。一旦它运行,其他所有线程都会被挂起来。

通过配置文件开启或者关闭并发和后台模式,(同一个配置项)

<configuration>
<runtime>
   <gcConcurrent enabled="false" />
</runtime>
</configuration

In workstation or server garbage collection, you can enable concurrent garbage collection , which enables threads to run concurrently with a dedicated thread that performs the garbage collection for most of the duration of the collection. This option affects only garbage collections in generation 2; generations 0 and 1 are always non-concurrent because they finish very fast.


Server GC 和Workstation GC都可以开启并发GC。在GC回收的过程中大部分时间用户线程可以并发运行。但这中效果只能影响到2带GC的过程,因为0代1代的时间太短了。

  Concurrent WS Non-Concurrent WS BackGround WS
(替代并发)
Server GC Server GC Background(替代并发)
出现时间 .net 1+ .net 1+<x<.net.4 .net 4+ .net 1+ .net 4.5.1+
设计目标 在吞吐量和界面相应速度上寻找平衡点 最大化吞吐量 在WS的设计基础上,优化gen2 GC性能 多处理器机器上使用多线程处理相同类型的请求以便最大化服务程序吞吐量 优化gen2 GC性能
GC Heap数量 1 1 1 1 per processor (HT aware) 1 per processor (HT aware)
GC threads 分配空间的线程会触发GC, 分配空间的线程会触发GC线程   每个处理器都有一个专职的GC线程 每个处理器都有一个专职的GC background线程
GC线程优先权 和工作线程具有相同的优先权 和工作线程具有相同的优先权 background GC线程与工作线程有相同优先级,但都低于前台GC线程 THREAD_PRIORITY_HIGHEST background GC线程与工作线程有相同优先级,但都低于前台GC线程
工作线程(非GC线程) GC工作过程中短暂多次挂起 GC工作过程中一直被挂起 GC工作过程中短暂多次挂起,较并发性能更加(针对Gen2的) GC工作过程中会被挂起 GC工作过程中短暂多次挂起,较并发性能更加(针对Gen2的)
ephemeral generation 的前台GC工作时会挂起其他所有线程
配置方式 <gcConcurrent enabled="true"> <gcConcurrent enabled="false"> <gcConcurrent enabled="false"> <gcServer enabled="true"> <gcConcurrent enabled="false">
是否会超时       不会

----------------------------------------------------------------------------------------------

Workstation GC

-------------------------------------------------------------------------------------------------

Server garbage collection

-------------------------------------------------------------------------------------------------


Concurrent garbage collection

-------------------------------------------------------------------------------------------------

Background workstation garbage collection

-------------------------------------------------------------------------------------------------

Background server garbage collection

-------------------------------------------------------------------------------------------------

其他相关

编程的内存模型中我们会接触到“堆”和“栈”两个部分。每个线程都有自己的栈,但共享堆(当然不是直接跨线程访问的意思,只能理解为共存在堆上)。

性能计数

What is the cost of a garbage collection? How can I keep this cost at a minimum?

You can measure the GC cost for your application with a few different counters. Remember that all of these counters are updated at the end of a collection which means that if you use averages they may not be valid after a long time of inactivity.

.NET CLR Memory\% time in GC - This counter measures the amount of CPU time you spend in GC and it is calculated as (CPU time for GC/CPU time since last GC)

.NET CLR Memory\# Induced GC – This is the number of garbage collections that have occurred as a result of someone calling GC.Collect(). Ideally this should be 0 since inducing full collections means that you spend more time in the GC, and also because the GC continuously adapts itself to the allocation patterns in the application, and performing manual GCs skews this optimization.

.NET CLR Memory\# Gen X collections – This counter displays the amount of collections that have been performed for a given generation. Since the cost of gen 2 collections is high compared to Gen 1 and Gen 0 you want to have as few Gen 2 collections per Gen 1 and Gen 0 collections as possible. A ratio of 1:10:100 is pretty good.

The most common causes for high CPU in GC or a high number of Gen 2 collections compared to 1 and 0 is high allocation of large objects and letting objects survive multiple generations because of improper use of finalizers or because finalizable objects are not disposed of correctly in the application.

参考

Finding garbage

.NET垃圾回收 – 原理浅析

How does the GC work and what are the sizes of the different generations?

垃圾回收

C#技术漫谈之垃圾回收机制(GC)

托管堆与垃圾收集

关于CLR内存管理一些深层次的讨论

http://blogs.msdn.com/maoni/archive/2004/06/15/156626.aspx

http://blogs.msdn.com/maoni/archive/2004/09/25/234273.aspx

垃圾回收翻译系列(√)

不得不知的CLR中的GC的更多相关文章

  1. 在 C# CLR 中学习 C++ 之了解 extern

    一:背景 在 CLR 源码中有很多的 extern 和 extern "C" 这样的关键词,比如下面这些代码: extern size_t gc_global_mechanisms ...

  2. CLR中的程序集加载

    CLR中的程序集加载 本次来讨论一下基于.net平台的CLR中的程序集加载的机制: [注:由于.net已经开源,可利用vs2015查看c#源码的具体实现] 在运行时,JIT编译器利用程序集的TypeR ...

  3. CLR中的垃圾回收机制

    CLR中采用代(generation)来作为其垃圾回收的一种机制,其唯一的目的是提升程序的性能.基予代的垃圾回收器有以下假设: ·对象越新,其生存周期越短. ·对象越老,其生存周期越长. ·回收堆的一 ...

  4. Unity中的GC以及优化

    [简介] 常见的 Unity GC 知识点总结出来的思维导图 Unity 官方文档,正巧在博客园发现了已经有位大神(zblade)把原文翻译出来了,而且质量很高~,译文地址 在这里.下面我就可耻地把译 ...

  5. 浅谈Unity中的GC以及优化

    介绍: 在游戏运行的时候,数据主要存储在内存中,当游戏的数据不在需要的时候,存储当前数据的内存就可以被回收再次使用.内存垃圾是指当前废弃数据所占用的内存,垃圾回收(GC)是指将废弃的内存重新回收再次使 ...

  6. [C#] 类型学习笔记一:CLR中的类型,装箱和拆箱

    在学习.NET的时候,因为一些疑问,让我打算把.NET的类型篇做一个总结.总结以三篇博文的形式呈现. 这篇博文,作为三篇博文的第一篇,主要探讨了.NET Framework中的基本类型,以及这些类型一 ...

  7. 警惕C#事件使用过程中的GC陷阱

    关于C#中的事件,园里已经有大量的文章对其内在实现做过剖析,如果还不甚了解的可以阅读这篇文章 通过Demo来细看C#事件的内在机制 虽然比较早,但非常清楚地展示了事件的内部机制,总结一下就是 1.事件 ...

  8. 如何诊断RAC系统中的'gc cr multi block request'?

    'gc cr multi block request' 是RAC数据库上比较常见的一种等待事件,在RAC 上进行全表扫描(Full Table Scan)或者全索引扫描(Index Fast Full ...

  9. 如何查看子线程中的GC Alloc

    1)如何查看子线程中的GC Alloc2)Build时,提示安卓NDK异常3)如何获得ParticleSystem产生的三角形数量4)关于图片通道的问题5)GPUSkinning导致模型动画不平滑 M ...

随机推荐

  1. ASP.NET Aries 入门开发教程1:框架下载与运行

    背景: 鉴于框架的使用者越来越多,文档太少,不少用户反映框架的入门门槛太高. 好吧,再辛苦下,抽时间写教程吧! 步骤1:下载框架源码 开源地址:https://github.com/cyq1162/A ...

  2. Convert BSpline Curve to Arc Spline in OpenCASCADE

    Convert BSpline Curve to Arc Spline in OpenCASCADE eryar@163.com Abstract. The paper based on OpenCA ...

  3. 玩转spring boot——结合JPA入门

    参考官方例子:https://spring.io/guides/gs/accessing-data-jpa/ 接着上篇内容 一.小试牛刀 创建maven项目后,修改pom.xml文件 <proj ...

  4. Unity3D 5.3 新版AssetBundle使用方案及策略

    1.概览 Unity3D 5.0版本之后的AssetBundle机制和之前的4.x版本已经发生了很大的变化,一些曾经常用的流程已经不再使用,甚至一些老的API已经被新的API所取代. 因此,本文的主要 ...

  5. [笔记]kubernetes 无法启动问题

    在启动kubernetes的时候报错误. ERROR: timed out for http://localhost:4001/v2/keys/ 原因是无法启动etcd, etcd 监听4001本地端 ...

  6. arcgis api for js入门开发系列六地图分屏对比(含源代码)

    上一篇实现了demo的地图标绘模块,本篇新增地图地图分屏对比模块,截图如下(源代码见文章底部): 对效果图的简单介绍一下,在demo只采用了两分屏对比,感兴趣的话,可以在两分屏的基础上拓展,修改css ...

  7. 如何理解DT将是未来IT的转型之路?

    如今的IT面临着内忧外患的挑战. 一方面,企业多多少少都建立了信息化,有些企业或集团甚至会有数几十个分公司,包含直销.代理.零售以及第三方物流等多种业态.越是复杂的业务,信息化建设越困难,比如运用大量 ...

  8. RMS:Microsoft Office检测到您的信息权限管理配置有问题。有关详细信息,请与管理员联系。(转)

    原文:https://zhidao.baidu.com/question/435088233.html RMS有两种方式: 1.使用微软的服务器,这个是连接到微软的服务器上面做权限控制,在今年5月份之 ...

  9. C#移动跨平台开发(2)Xamarin移动跨平台解决方案是如何工作的?

    概述 上一篇 C#移动跨平台开发(1)环境准备发布之后不久,无独有偶,微软宣布了开放.NET框架源代码并且会为Windows.Mac和Linux开发一个核心运行时(Core CLR),这也是开源的!I ...

  10. C#分布式消息队列 EQueue 2.0 发布啦

    前言 最近花了我几个月的业余时间,对EQueue做了一个重大的改造,消息持久化采用本地写文件的方式.到现在为止,总算完成了,所以第一时间写文章分享给大家这段时间我所积累的一些成果. EQueue开源地 ...