GC 为何会导致线程数降低?

作者:张松然

简介:京东商城,商家研发部架构师。丰富的构建高性能高可用大规模分布式系统的研发、架构经验。2013年加入京东,目前负责京麦服务市场的系统研发工作。

疑惑

近期收到一些报警,是方法性能报警,定位原因主要是瞬时流量突增引起的,但是观察方法中查询 MySQL 的性能不差,性能花费在哪里?同时观察 JVM 性能,发现 YoungGC 变多了,CPU 使用率高了,但线程数在当时刻降低了,YoungGC 会创建新线程进行垃圾回收,应该线程数增多,为什么会降低的?

解惑

性能为什么慢了?

由于提供服务的 API 所依赖的 MySQL 性能并不慢,那原因是什么?唯一的问题点就是流量,流量突增引发系统开启大量线程进行处理,线程状态处于 Running 或 Runable 状态,这时操作系统(分时操作系统)会让 CPU 进行分时处理,从而引发 CPU 使用率上升。多线程并发处理会让服务器处理速度变快,但对于单个服务响应会变慢。

还有我们一般的系统架构部署多是 Nginx - Tomcat,而 Tomcat 默认线程数多是1000上限,且Tomcat 7以下版本默认是 BIO 模式,超过上限的线程会在 Tomcat 阻塞队列里等待,所以对于调用方来说,感知的时间会更久一些。

线程数为什么减少?

我们查看 JVM 的是配置内容,Young GC 是 PS Scavenge,Full GC 是 PS MarkSweep。

(本图引自网络)

并行(Parallel)指多条 GC 线程并行工作,但此时用户线程处于等待状态。并发(Concurrent)指用户线程与 GC 线程同时执行(不一定是并行的,可能会是交替执行);用户程序线程继续运行,而垃圾收集线程运行于另一个 CPU 上。

所以,Young GC 是 PS Scavenge,在 GC 时会出现 stop-the-world 的情况,此时用户线程处于阻塞情况,所以瞬时线程数会降低,当 GC 结束后,用户线程会恢复执行,所以又会上去。

为什么会发生这么多 Young GC?

Young GC 是对 Young Generation 的垃圾收集,YGCeden 空间不足会进行 Eden 和 Survivor 的 YGC。一个线程会在内存创建一个堆栈的空间,多线程会频繁的创建和释放内存空间,所以 YGCeden 会进行频繁的垃圾回收,因此会发生这么多 YGC。

我们知道 JVM 大多数采用主动式中断,即 GC 需要中断线程的时候,它就设个标志位(safe-point),执行线程会主动轮询这个标志位,如果标志位就绪的话就自行中断。

堆内存为什么减少了?

我们观察到堆内存的使用情况也降低了。

这是因为 PS MarkSweep 是标记-清除算法,PS Scavenge 是复制算法,GC 回收是进行内存无引用的内存回收,所以会让对内存占用减少。

思考

考虑现有系统的应用场景,如果是网关系统,频繁的 Young GC 和 Full GC 在 stop-the-world 发生时,一定会影响调用方请求,极端情况下出现 502 的问题。所以,在设计系统的时候,还是要尽量减少 Young GC 和 Full GC。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值