各类GC及触发条件

针对HotSpot VM的实现,它里面的GC其实准确分类只有两大种:

  • Partial GC:并不收集整个GC堆的模式
  • Young GC:只收集young gen的GC
  • Old GC:只收集old gen的GC。只有CMS的concurrent collection是这个模式
  • Mixed GC:收集整个young gen以及部分old gen的GC。只有G1有这个模式
  • Full GC:收集整个堆,包括young gen、old gen、perm gen(如果存在的话)等所有部分的模式。

Major GC通常是跟full GC是等价的,收集整个GC堆。但因为HotSpot VM发展了这么多年,外界对各种名词的解读已经完全混乱了,当有人说“major GC”的时候一定要问清楚他想要指的是上面的full GC还是old gen。

最简单的分代式GC策略,按HotSpot VM的serial GC的实现来看,触发条件是:
**young GC:**当young gen中的eden区分配满的时候触发。注意young GC中有部分存活对象会晋升到old gen,所以young GC后old gen的占用量通常会有所升高。
full GC:当准备要触发一次young GC时,如果发现统计数据说之前young GC的平均晋升大小比目前old gen剩余的空间大,则不会触发young GC而是转为触发full GC(因为HotSpot VM的GC里,除了CMS的concurrent collection之外,其它能收集old gen的GC都会同时收集整个GC堆,包括young gen,所以不需要事先触发一次单独的young GC);或者,如果有perm gen的话,要在perm gen分配空间但已经没有足够空间时,也要触发一次full GC;或者System.gc()、heap dump带GC,默认也是触发full GC。这就是FullGC的触发条件
HotSpot VM里其它
非并发
GC的触发条件复杂一些,不过大致的原理与上面说的其实一样。
当然也总有例外。Parallel Scavenge(-XX:+UseParallelGC)框架下,默认是在要触发full GC前先执行一次young GC,并且两次GC之间能让应用程序稍微运行一小下,以期降低full GC的暂停时间(因为young GC会尽量清理了young gen的死对象,减少了full GC的工作量)。这是HotSpot VM里的奇葩嗯。

并发GC的触发条件就不太一样。以CMS GC为例,它主要是定时去检查old gen的使用量,当使用量超过了触发比例就会启动一次CMS GC,对old gen做并发收集。这里就是只回收老年代了!

从携程apollo拷贝过来的JVM参数,看一下他们用了哪些JVM参数

-Xms6144m -Xmx6144m -Xss256k -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=384m -XX:NewSize=4096m -XX:MaxNewSize=4096m -XX:SurvivorRatio=8
-XX:+UseParNewGC -XX:ParallelGCThreads=4 -XX:MaxTenuringThreshold=9 -XX:+UseConcMarkSweepGC -XX:+DisableExplicitGC -XX:+UseCMSInitiatingOccupancyOnly -XX:+ScavengeBeforeFullGC -XX:+UseCMSCompactAtFullCollection -XX:+CMSParallelRemarkEnabled -XX:CMSFullGCsBeforeCompaction=9 -XX:CMSInitiatingOccupancyFraction=60 -XX:+CMSClassUnloadingEnabled -XX:SoftRefLRUPolicyMSPerMB=0 -XX:+CMSPermGenSweepingEnabled -XX:CMSInitiatingPermOccupancyFraction=70 -XX:+ExplicitGCInvokesConcurrent -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCApplicationConcurrentTime -XX:+PrintHeapAtGC -XX:+HeapDumpOnOutOfMemoryError -XX:-OmitStackTraceInFastThrow -Duser.timezone=Asia/Shanghai -Dclient.encoding.override=UTF-8 -Dfile.encoding=UTF-8 -Djava.security.egd=file:/dev/./urandom

UseCMSCompactAtFullCollection和CMSFullGCsBeforeCompaction是搭配使用,两个参数缺一不可,才能实现指定次数Full GC后对老年代进行压缩,因为老年代是标记清除。

-XX:+ScavengeBeforeFullGC -XX:+CMSScavengeBeforeRemark指导垃圾回收机制在进行Full GC和CMS remark phase之前收集年轻态。其结果是提升性能,因为在年轻态和老态之间不存在检查引用。

-XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=

缺省的 CMS GC使用的启发式规则触发垃圾回收,这会让GC不太能预测,一般直至老生代空间被几乎占满后才会启动垃圾回收,Initiating设置能够使得在老生代变满之前完成回收,避免Full GC (这就意味着整个应用程序暂停无响应stop-the-world pause). -XX:+UseCMSInitiatingOccupancyOnly 阻止使用启发式规则 -XX:CMSInitiatingOccupancyFraction 通过JVM应该在什么时候启动触发回收,它会在heap中创建一个buffer,这个缓冲当CMS工作时能用数据填充,其内存被消耗的速度百分比可衡量老生代生产环境中的消耗。这个百分比数值应该小心选择,太小CMS太频繁,太大CMS启动频率太少,并发模式可能会失败。

XX:+CMSParallelRemarkEnabled

启动并发标记,提高效率。

03-27
### C# 垃圾回收机制的工作原理 C# 的垃圾回收(Garbage Collection, GC)由 .NET 运行时(CLR)负责管理和执行。其核心目标是自动管理应用程序的内存分配和释放,从而减少开发人员的手动干预。以下是关于 C# 垃圾回收机制工作原理的关键点: #### 1. **垃圾回收的核心概念** 垃圾回收的主要功能是从托管堆中移除不再使用的对象,并重新利用这些已释放的空间来分配新对象。这一过程通过多种算法实现,主要包括标记-清除、标记-整理以及分代收集。 - **标记-清除(Mark and Sweep)** 此算法遍历所有根对象(如全局变量或栈上的局部变量),并将可达的对象标记为存活状态。随后,未被标记的对象会被视为垃圾并清理掉[^1]。 - **标记-整理(Mark and Compact)** 类似于标记-清除,但在清理阶段还会将剩余的活动对象移动到连续的内存区域,以消除碎片化问题。 - **分代收集(Generational Collection)** CLR 将托管堆划分为三代:0代、1代和2代。新生对象通常位于第0代,随着多次生存周期逐渐晋升至更高代次。这种设计基于“大多数对象寿命较短”的假设,能够显著提升性能[^3]。 #### 2. **垃圾回收的过程** 当触发条件满足时,GC 开始执行以下操作: - **标记阶段**:识别哪些对象仍处于活跃状态。 - **重置阶段**:更新引用计数或其他内部结构。 - **扫描阶段**:查找不可达对象并准备销毁。 - **压缩阶段**(仅适用于某些模式):整理内存布局以防止碎片化。 #### 3. **手动触发垃圾回收** 虽然 GC 是自动化的,但开发者可以通过 `System.GC` 提供的方法显式请求一次完整的垃圾回收流程。例如,在特定场景下可以调用如下代码片段强制执行 GC: ```csharp // 显式触发垃圾回收 GC.Collect(); // 等待最终化队列清空 GC.WaitForPendingFinalizers(); Console.WriteLine("垃圾回收完成"); ``` 需要注意的是,频繁地手动触发可能会干扰正常的程序运行效率,因此应谨慎使用上述方法[^2]。 --- ### 配置垃圾回收的行为 为了适应不同应用场景的需求,.NET 平台提供了灵活的方式来调整 GC 行为。主要涉及以下几个方面: #### 1. **设置服务器 vs 工作站模式** 可以根据部署环境选择合适的 GC 模型: - **工作站模式**:适合桌面应用,默认启用后台线程辅助进行并发收集。 - **服务器模式**:专为多核处理器优化,每 CPU 核心拥有独立的堆实例,提高吞吐量却可能增加暂停时间。 可通过配置文件指定该选项,比如在 app.config 或 web.config 文件里加入下面的内容切换成 Server Mode: ```xml <configuration> <runtime> <gcServer enabled="true"/> </runtime> </configuration> ``` #### 2. **调节延迟优先级** 对于实时性要求较高的场合,允许降低常规 GC 的频率以便维持较低的响应延迟。这被称为低延迟模式(Low Latency Mode)。同样支持通过 AppDomain API 动态开启此特性。 #### 3. **监控与诊断工具的应用** 借助 Visual Studio Profiler 和 PerfView 等高级分析软件可以帮助深入理解实际项目里的内存消耗状况及其背后原因,进而指导进一步改进措施。 --- ### 总结 综上所述,C# 的 Garbage Collection 不仅简化了日常编程任务中的资源管理工作,还具备高度可定制的能力去匹配各类复杂业务需求下的表现期望。然而合理规划对象生命期仍是避免潜在性能瓶颈的重要环节之一。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值