JVM调优学习之旅-(4)G1

G1垃圾回收器介绍

G1垃圾回收器在我们设置堆内存大小后,JVM启动在默认情况下把堆内存拆分为大小均等的region具体大小是—堆内存/2048。region大小是2的倍数。

可以通过 “-XX:G1HeapRegionSize” 设置region大小。

region 数量是动态的。初始的时候新生代region只有5%,会随着新生代增加region跟着增加。 垃圾回收后也会减少。默认新生代的占比不会超过60%,可以通过**“- XX:G1MaxNewSizePercent”**设置

新生代

新生代也是有eden区 s1,s2 的区别的他们的数量也是根据region的增加而增加,也是根据一定比例来决定的。“-XX:SurvivorRatio=8”

什么时候进入老年代
  1. 当年龄到了会进入老年代,年龄设置**“-XX:MaxTenuringThreshold”** 默认15
  2. 动态年龄规划或某一次发生GC后存货对象大于s区一半。
大对象去哪了

G1 会有专门的region 存放大对象,甚至一个大对象可以放几个region。由于新生代region是逐渐变大,所以大对象是在还没分配新生代的时候,region 就是用来存放大对象的。新生代 老年代GC 都会来回收大对象。

G1垃圾回收的过程
  1. 初始标记:先STW,然后对各个线程栈内存中的局部变量代表的GC Roots,以及方法区中的类静态变量代表的GC Roots,进行扫描,标记出来他们直接引用的那些对象。
  2. 并发标记:通过gc roots 追踪全部对象。并且会标记在这期间有哪些对象修改。(比如说哪个对象被新建了,哪个对象失去了引用)
  3. 最终标记阶段:先STW,但是会根据并发标记 阶段记录的 那些对象修改,最终标记一下有哪些存活对象,有哪些是垃圾对象。
  4. 混合回收阶段:会STW,这个阶段会计算老年代中每个Region中的存活对象数量,存活对象的占比,还有执行垃圾回 收的预期性能和效率。然后在限定的时间范围内尽可能回收对象。会选择部分Region进行回收,因为必须让垃圾回收的停顿时间控制在我 们指定的范围内。
public class Kafka {
	public static ReplicaManager replicaManager = new ReplicaManager();
    //第一阶段标记直接引用与对应的ReplicaManager类
}
public class ReplicaManager {
    // 第二阶段标记通过gc roots replicaManager 追踪 replicaFetcher这个实例变量 发现引用了 ReplicaFetcher对象
	public ReplicaFetcher replicaFetcher = new ReplicaFetcher();
}
什么时候自动触发新生代+老年代的混合垃圾回收

G1有一个参数,是“-XX:InitiatingHeapOccupancyPercent”,他的默认值是45%;当老年代占据堆内存45% 就会尝试触发一个新生代+老年代一起回收的混合回收阶段。 又称Mixed GC

混合回收过程

由于混合回收由于停顿时间的原因,会有多次。有一些参数可以控制这个,比如**“-XX:G1MixedGCCountTarget”**参数,就是在一次混合回收的过程中,最后一个阶段执行几次混合 回收,默认值是8次

因为你停止系统一会儿,回收掉一些Region,再让系统运行一会儿,然后再次停止系统一会儿,再次回收掉一些Region,这样可以尽 可能让系统不要停顿时间过长,可以在多次回收的间隙,也运行一下。

还有一个参数,就是**“-XX:G1HeapWastePercent”**,默认值是5% 他的意思就是说,在混合回收的时候,对Region回收都是基于复制算法进行的,都是把要回收的Region里的存活对象放入其他 Region,然后这个Region中的垃圾对象全部清理掉。一旦空闲出来的Region数量达到了堆内存的5%,此时就会 立即停止混合回收,意味着本次混合回收就结束了。

而且从这里也能看出来G1整体是基于复制算法进行Region垃圾回收的,不会出现内存碎片的问题,不需要像CMS那样标记-清理之 后,再进行内存碎片的整理。

还有一个参数,“-XX:G1MixedGCLiveThresholdPercent”,他的默认值是85%,意思就是确定要回收的Region的时候,必须是存 活对象低于85%的Region才可以进行回收 否则要是一个Region的存活对象多余85%,你还回收他干什么?这个时候要把85%的对象都拷贝到别的Region,这个成本是很高的。

回收失败

由于是给予复制算法进行回收,那么再拷贝的过程发现存活的对象没有地方放得下,那么会触发失败,会停止系统程序,然后采用单线程标记算法来回收。很慢。

从上面可以看出G1非常适合大内存的系统和延时要求较小的系统,例如实时通信,因为parnew垃圾回收器如果是大内存的话,在垃圾回收期间,会有很长的停顿时间,而G1可以控制每次回收停顿时间。

G1垃圾回收模拟分析

一个在线教育系统  高峰期在每天晚上 持续2-3小时
估算 
3小时 差不多有60万的用户在线 平均一个用户差不多一个小时在线时长 
那么每小时大概会有20万活跃用户同时在线学习。
由于有互动效果, 每个用户平均一分钟互动一次 
20万用户一小时差不多1200万次互动
那么每秒差不多压力有3000
5台 4c8g的机器  平均每秒可以抗住600请求
所有大致估算一下,一次互动请求大致会连带创建几个对象,占据几KB的内存,比如我们就认为是5KB吧那么一秒600请求会占用3MB左右的内存。

我们采用G1垃圾回收器

4G堆内存
那么假设我们对机器上的JVM,分配4G给堆内存,其中新生代默认初始占比为5%,最大占比为60%,每个Java线程的栈内存为1MB,元数据区域(永久代)的内存为256M,此时JVM参数如下 
-Xms4096M -Xmx4096M -Xss1M -XX:PermSize=256M -XX:MaxPermSize=256M -XX:+UseG1GC
“-XX:G1NewSizePercent”参数是用来设置新生代初始占比的,不用设置,维持默认值为5%即可。
“-XX:G1MaxNewSizePercent”参数是用来设置新生代最大占比的,也不用设置,维持默认值为60%即可。
此时堆内存共4G,那么此时会除以2048,计算出每个Region的大小,此时每个Region的大小就是2MB,
刚开始新生代就占5%的Region,可以认为新生代就是只有100个Region,有200MB的内存空间

在G1垃圾回收器中有一个至关重要的参数会影响到GC的表现,就是“-XX:MaxGCPauseMills”,他的默认值是200 毫秒

也就是说咱们希望每次触发一次GC的时候导致的系统停顿时间(也就是“Stop the World”)不要超过200毫秒,避 免系统因为GC长时间卡死。

分析

G1会根据停顿时间的长度来估算回收时间,意思就是

每秒创建3M大的新生代 差不多一分钟就塞满200m  这时回收只需要几十毫秒 G1这时是不会回收的 
G1可能会凑够差不多200ms才开始回收。 这个是无法精准预测的!只有具体拿工具查看。

停顿时间到底应该怎么设置

设置小了 频繁gc 虽然说时间短,但是会让对象更快进入老年代 会频繁 mixed GC
设置大了 此时可能一次GC停顿时间就会达到几百毫秒,但是GC的频率很低。比如说30分钟才触发一次新生代GC,但是每次停顿500毫秒。

所以这个参数到底如何设置,需要结合后续给大家讲解的系统压测工具、gc日志、内存分析工具结合起来进行考虑,尽量让系统的gc频率别太高,同时每次gc停顿时间也别太长,达到一个理想的合理值

G1与parnew+cms的区别点
g1和pn+cms调优原则都是尽可能ygc,不做老年代gc。 g1相对而言更加智能,也意味着jvm会用更多的资源去判断每个region的使用情况。
而pn+cms也更加纯粹和直接,虽然g1在gc时不会产生碎片,但是由于每个region存在存活率85%不清理的机制,会导致内存没有充分利用与释放问题。
因此,对于cpu性能高的,内存容量大的,对应用响应度高的系统推荐使用g1。 而内存小,cpu性能比较低下的系统也可以使用pn+cms会更合适

parallel scavenge与 parnew两者都是复制算法,都是并行处理,但是不同的是,parallel scavenge 可以设置最大gc停顿时间(-XX:MaxGCPauseMills)以及gc时间占比(-XX:GCTimeRatio)

parallel scavenge更关注 吞吐量 ,不过目前系统喜欢吞吐量的基本都用G1了。

G1也可以做到 parallel scavenge+Parallel Old的功能

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值