引言

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. NodeJs之调试

    关于调试 当我们只专注于前端的时候,我们习惯性F12,这会给我们带来安全与舒心的感觉. 但是当我们使用NodeJs来开发后台的时候,我想噩梦来了. 但是也别泰国担心,NodeJs的调试是很不方便!这是 ...

  2. ASP.NET Core 中的那些认证中间件及一些重要知识点

    前言 在读这篇文章之间,建议先看一下我的 ASP.NET Core 之 Identity 入门系列(一,二,三)奠定一下基础. 有关于 Authentication 的知识太广,所以本篇介绍几个在 A ...

  3. SQL Server2014 SP2新增的数据库克隆功能

    SQL Server2014 SP2新增的数据库克隆功能 创建测试库 --创建测试数据库 create database testtest use testtest go --创建表 )) --插入数 ...

  4. Mono为何能跨平台?聊聊CIL(MSIL)

    前言: 其实小匹夫在U3D的开发中一直对U3D的跨平台能力很好奇.到底是什么原理使得U3D可以跨平台呢?后来发现了Mono的作用,并进一步了解到了CIL的存在.所以,作为一个对Unity3D跨平台能力 ...

  5. Socket聊天程序——客户端

    写在前面: 上周末抽点时间把自己写的一个简单Socket聊天程序的初始设计和服务端细化设计记录了一下,周二终于等来毕业前考的软考证书,然后接下来就是在加班的日子度过了,今天正好周五,打算把客户端的详细 ...

  6. HTML骨架结构

    前面的话   一个完整的HTML文档必须包含3个部分:文档声明.文档头部和文档主体.而正是它们构成了HTML的骨架结构.前面已经分别介绍过文档声明和文档头部,本文将详细介绍构成HTML骨架结构的基础元 ...

  7. AFNetworking 3.0 源码解读(七)之 AFAutoPurgingImageCache

    这篇我们就要介绍AFAutoPurgingImageCache这个类了.这个类给了我们临时管理图片内存的能力. 前言 假如说我们要写一个通用的网络框架,除了必备的请求数据的方法外,必须提供一个下载器来 ...

  8. 6.在MVC中使用泛型仓储模式和依赖注入实现增删查改

    原文链接:http://www.c-sharpcorner.com/UploadFile/3d39b4/crud-operations-using-the-generic-repository-pat ...

  9. Lind.DDD.LindAspects方法拦截的介绍

    回到目录 什么是LindAspects 之前写了关于Aspects的文章<Lind.DDD.Aspects通过Plugins实现方法的动态拦截~Lind里的AOP>,今天主要在设计思想上进 ...

  10. Android之解析XML

    1.XML:可扩展标记语言. 可扩展标记语言是一种很像超文本标记语言的标记语言. 它的设计宗旨是传输数据,而不是显示数据. 它的标记没有被预定义.需要自行定义标签. 它被设计为具有自我描述性. 是W3 ...