连载中 8/20

经典收集器:吞吐量与停顿时间的第一次分家

2026-09-14 · 60 阅读 · 0 评论 · 0 赞

两个门派

GC 的世界有一场持续至今的分家:吞吐量优先关注总账——单位时间里干完的活最多,单次停顿长点无所谓;延迟优先关注体验——每次停顿都要短,哪怕总开销更大。批处理跑数、离线计算选前者;在线交易、面向用户的服务选后者。所有收集器都可以放进这张坐标系里看。

新生代三件套

Serial:单线程收集,收集时全停顿——简单高效没废话,客户端和小内存场景至今在用;ParNew:Serial 的多线程版,为配合 CMS 而生;Parallel Scavenge:也是多线程,但目标是可控的吞吐量,提供 -XX:MaxGCPauseMillis 和 -XX:GCTimeRatio 两个旋钮,还支持自适应调节(GC 自动向代尺寸要空间)。JDK 8 的默认组合是 Parallel Scavenge + Parallel Old——服务端吞吐优先的务实选择。

CMS:并发收集的第一位选手

// CMS 老年代回收四阶段
// 1. 初始标记  STW,极短:只标记 GC Roots 直接关联的对象
// 2. 并发标记  与用户线程并行:沿着引用链摸完整堆(最耗时但不停顿)
// 3. 重新标记  STW,较短:修正并发期间用户线程改动的部分
// 4. 并发清除  与用户线程并行:把死对象就地清掉(标记-清除算法)
//
// 精髓:把最耗时的活儿挪到并发阶段,STW 只剩两个短环节
// 代价:并发=和业务抢 CPU;清除=留下碎片

CMS 的三宗罪

一,CPU 敏感:并发阶段默认占(核数+3)/4 的线程,核少时业务明显变慢。二,浮动垃圾:并发标记和清除期间产生的新垃圾只能等下轮,如果老年代增长太快、清理前就满了,并发模式失败(Concurrent Mode Failure),JVM 会启动保命方案——Serial Old 单线程整理整堆,一次超长 STW,比不用 CMS 还惨。缓解办法是把 -XX:CMSInitiatingOccupancyFraction(默认 92%)调低、提前触发,但调太低又浪费 GC 次数。三,碎片:标记-清除不给对象搬家,碎片积累到分配不出连续空间,只能靠 Full GC 前的压缩救场。这三宗罪注定了 CMS 的退场——JDK 9 被标记废弃,JDK 14 彻底移除。

经典组合速查

新生代老年代定位
SerialSerial Old单线程,客户端/小内存
ParNewCMS + Serial Old 兜底延迟优先(JDK 8 时代主流)
Parallel ScavengeParallel Old吞吐优先,JDK 8 默认

CMS 教会业界一件事:停顿可以并发化,但"边干活边搬家"在当时做不到——所以它只能选清除,只能留碎片。把并发化和"无碎片"同时做到的,是下一篇的主角 G1。

☕
503

10 年全栈工程师 · 503咖啡馆主理人

#CMS收集器#Parallel#吞吐量优先#延迟优先#Concurrent Mode Failure

评论 (0)

热门推荐

连载中 11/22

主从搭建实操:从零配出一主两从

光讲原理不过瘾?手把手搭一主两从:my.cnf 六个参数、复制账号、GTID、CHANGE REPLICATION SOURCE TO、SHOW REPLICA STATUS 验收,附翻车排查清单。

#MySQL#主从复制#GTID#主从搭建#高可用
2026-05-07 · 10101 阅读 · 0 评论 · 0 赞
连载中 16/22

连接池:HikariCP 参数与连接风暴

连接池不是越大越好:8 核机器配 1000 连接反而更慢的数学原理,HikariCP 四个必调参数,maxLifetime 与 wait_timeout 的隐形陷阱。

#MySQL#连接池#HikariCP#maxLifetime#连接风暴
2026-05-10 · 9873 阅读 · 0 评论 · 0 赞
连载中 4/16

缓存穿透:恶意 ID 打穿 MySQL 的四道防线

请求的数据在缓存和数据库里都不存在时,缓存形同虚设。聊聊参数校验、空值缓存、布隆过滤器、限流熔断四道防线的原理与组合打法。

#Redis#缓存穿透#布隆过滤器#高可用
2026-05-16 · 9294 阅读 · 21 评论 · 287 赞