爱看书的阿东

赐他一块白色石头,石头上写着新名

深入理解JVM - G1调优简述

前言

​ G1收集器是一个不太好调优的收集器,因为他不能像固定分代的收集器那样可以自己想划分多少就划分多少,更多的分配动作是由收集器动作,由于region是一块块的,同时自动增长也是由G1控制,好像确实不太好调优。

​ 这篇文章更多的是提供调优的一个大致方向,更多的内容需要后续介绍JVM的工具进行讲解。

案例实战

​ 这次使用一个在线的教育平台作为案例解释G1是如何进行优化的。

​ 在线教育平台的压力来自于哪里?首先孩子白天需要上学同时家长也需要上班,所以白天的访问量不会很大,同时主要的业务也不在在线教育平台处理。但是一旦到了晚上,机器的压力就上来了,同时孩子也会在线进行听课上课,这时候用户量会暴增,会有上万人同时在线听课。这时候可以发现在线教育平台的压力在于直播,而直播的流量高峰在于课堂的互动环节,为什么是互动环节呢,因为孩子不喜欢枯燥的课堂,为了带动课堂氛围,课堂中的游戏一定是活跃气氛的关键,也是系统压力的核心,这时系统需要记录各种数据,比如活动时长,得分,积分奖励等等,同时也会出现大量的对象分配,为了保证直播的流畅,系统要求十分低的延迟响应时间。

​ 所以最终的结论是:在线教育平台大概在直播的互动环节压力会倍增,系统要求十分低的延迟响应时间。

​ 经过了上面的情况分析,我们假设单台机器每秒大概有600个请求,假设每一个请求占用10KB,则是6000KB的大小占用也就是最终6M左右的内存占用。同时部署在一个4核心8G的系统上面。

同样的,这种案例也只是模拟和假设,具体情况受到各种因素的限制,切勿过于深究细节。

如何分析系统

传统的分代概念

​ 我们用传统分代的概念部署一下这个系统,根据每一秒的请求为6M的对象大小,同时根据系统4核心8的配置,那么给JVM的内存大概是4G,我们知道直播的互动环节产生的积分,奖励,计算等对象基本都是朝生夕死的小对象,所以我们不太需要给老年代过大的空间,所以出去方法区和虚拟机线程栈的内存,我们给大约会给新生代3G和老年代1G左右的内容。

​ 如果每秒产生6M的对象,那么一分钟就是300多M,按照默认的新生代配比8:1:1则Eden区域大概为2.4G的大小,survior区域为两个300M的大小空间。一分钟300M,那么基本上8分钟左右新生代就会满,此时假设有300M左右对象存活进入Survior区域,这时候Survior区域虽然可以装的下,但是由于超过了50%的配比,最终还是有约150M的对象进入老年代。

​ 这时候再推算,老年代每8分钟进入150M的对象,大约40分钟左右就会整个系统停顿一次,这个停顿时间还是乐观估计,因为系统不可能只运作这一块的内容,单单是推算直播互动这一块就会产生这样的效果,可想而知加上整个系统的其他模块,实际上5、6分钟可能会停顿一次!!!这样肯定是不行的,试想下你玩游戏隔几分钟就停一下,对于小孩子来说突然卡一下导致丢分最后成绩不佳孩子又哭又闹,家长这时候不用想肯定会大量的投诉,被骂也不远了……

使用G1收集器

​ 我们接着使用G1的收集器进行替换,系统部署在一个4核心8G的系统上面,假设机器在JVM上分配4G给堆,新生代默认初始化比例为5%,最大占比为60%,JAVA线程堆栈为1M,则大约开启几百个线程需要200,300M的空间,而方法区占用256M够用。

​ 在上一节在文章中介绍过,可以把G1的工作机制想象成收盘子,但是放到系统上就很头疼了,G1什么时候回来收垃圾是我们无法预测的!!这里就需要通过一些辅助手段,同时这部分的监控操作需要工具和日志进行解读,所以将会放到后续的专门一篇文章进行解读。

如何计算Region的占用和大小:

​ 按照4096M/2048 每个region是2M,如果按照新生代初始为5%,则根据参数5%新生代的大小为100个Region左右,4G的内存机器结果可以得出新生代初始200M左右的内存占用大小

至关重要的参数:

-XX:MaxGCPauseMills 参数:默认值为200,代表了200MS,表示最大的停顿时间为200MS。

​ 如果使用G1收集器,这个参数直接影响了整个JVM系统的性能,如果这个数值过大,会导致垃圾收集的时间过长而导致前台卡顿,也容易导致新生代来不及触发垃圾回收就满了,或者导致老年代内存无法及时的回收。

多久会触发新生代回收操作

​ 根据之前的说明,新生代最大可以使用60%的空间,同时也说明了新生代使用复制算法,根据8:1:1的规则,大概到达新生代的80%左右就会触发垃圾的回收操作?这种做法显然不符合G1基于全堆以及混合回收的操作。所以不能用固定大小的回收思路思考g1的回收操作。

​ 正确做法: G1会根据200MS的要求,定时去判定当前的新生代是否可以符合200MS的收集操作要求,大意就是当新生代的垃圾回收需要耗时200MS的时候,就会触发新生代的回收。

​ 这里也可以直接按照之前的理解餐厅的服务员定时过来收盘子的操作理解新生代多久进行一次回收操作。

如何优化:

​ 上面的讨论几点之后,这就头疼了,这要这么优化?这时我们需要用上一些压测的工具以及GC日志和内存分析工具来考虑了,但是也不要让GC挺多停顿时间预设值太大了导致GC停顿时间太长,应该给个合理的值。

Mixed gc如何优化?

​ 既然新生代的优化都已经很麻烦了,更不用说老年代回收了。而老年代的回收本身也没有了Old GC,取而代之的是Mixed GC,所以需要小心对待,我们从根本上还是需要防止让对象进入到老年代不断扩展导致mixed gc,这更加需要关注时间停顿模型这个参数。

最终分析

​ 新生代:

  1. 由于是复制算法,所以需要从根本上处理的话依然需要控制新生代的存活对象进入survior的大小,同时控制在50%以内。尽量避免GC之后对象直接进入老年代。另外60%的新生代空间通常也不用怎么调整,除非业务对象频繁创建新生代会产生大量对象才需要考虑。
  2. 新生代有一个参数是存活对象大于85%的时候不需要进行拷贝,这个值如果设置小一点可能会提高回收效率,但是有可能造成大量的短命对象进入老年代的风险。

​ 老年代:

  1. 按照G1的最后一个步骤,垃圾回收和系统回交替8次,同时在回到5%的region的时候停止收集,这个参数其实可以适当调大一些:G1HeapWastePercent
  2. 45%的老年代占用触发垃圾回收的机制,这个参数也不需要大改,因为JDK设置这个参数肯定是经过了很多测试和考量之后的结果。

总结

​ 这一篇更多的是提供优化思路,JVM调优没有万金油的解决方案,特别是G1收集器这种算法细节十分复杂的收集器,调优需要更多的精力和时间测试调优效果。

写在最后

​ 下一篇章会做一个整个系列到目前为止的小节,温故而知新,人的遗忘曲线更加需要我们反复的巩固知识和内容。

深入理解JVM - G1收集器

前言

​ 上一篇通过案例说明了老年代的常见优化和处理方式,这一节来看下目前最为热门的G1收集器,G1收集器也是JDK9服务端默认的垃圾收集器,虽然JDK9在现在看来还不是十分的普及,但是学习这个垃圾收集器是十分重要也是十分必要的。

阅读全文 »

《卓有成效的管理者》读书笔记

[TOC]

资源地址

1
2
3
链接:https://pan.baidu.com/s/1ofjDGOVNZkSJ7tJ2X1fOJA 
提取码:41dv
--来自百度网盘超级会员V6的分享

前言

​ 知道这本书的名字是从网上的思维导图里面看到的,实际看了一下发现还不错的一本书,这篇笔记就来看一下这本书的读书笔记。

推荐语

​ 虽然你可能不是管理者,但是这本书依然对你有用,明白什么样的领导是好领导,跟对人和做对事永远是最重要的事情。

个人评价

​ 4星。可能很多人会觉得这本书可能跟自己压根没有关系,然而管理人员是一门很深的学问,如果你要当过组长或者带领过其他人,相信这本书给你的感受是完全不一样的。

阅读全文 »

深入理解JVM - 实战老年代优化

[TOC]

前言

​ 通过前面的文章可以了解到JVM优化中老年代的FULL GC对于系统以及垃圾收集器的行为有着十分大的影响,比如CMS并发标记或者回收撑不住的时候要暂停用户线程并且呼叫serrial收集器帮忙进行单线程的高效回收的动作,但是也伴随着”漫长”的stop world时间。

​ 综上所述,老年代的优化是JVM优化的一个核心知识点,所以这一节就来讲解如何优化老年代的回收,尽量让对象在新生代回收而不是在老年代进行回收。

阅读全文 »

深入理解JVM - 垃圾回收算法

前言:

​ 这一期讲述垃圾回收的算法。我们根据分代的理念讲述一下JVM是使用什么算法对于不同分代的对象进行垃圾回收的的,同样内容十分基础,但是对于学习JVM后续的内容十分重要。

前文回顾

​ 在上一节当中,我们看到了JVM当中堆将分为新生代和老年代,对象优先在新生代分配,以及新生代在长期存活并且满足条件之后进入老年代,介绍了新生代的Minor Gc和老年代的Full GC,最后,我们用下面的一张图了解到一个对象分配的大致流程,以及JVM的内存核心参数配置以及方法区的回收条件等。

对象分配的细节

阅读全文 »

《MySQL必知必会》读书笔记

前言

​ 第一次完整的技术书籍的读书笔记,这本书200多页,看起来轻松又简单,当然因为内容本身非常基础的缘故,这本书我也只是翻了一遍,等接触到具体内容的时候可以拿起来再看看,看这本书的意义就在于此。

资源链接:

1
2
3
链接:https://pan.baidu.com/s/1RnsH_-HjTCgKOKlxWg4dTg 
提取码:6nta
--来自百度网盘超级会员V6的分享
阅读全文 »

《微习惯》读书笔记

前言

​ 《微习惯》这本书算是老外对于“不积跬步无以至千里”这句话的个人经验讲解。

资源链接:

链接:https://pan.baidu.com/s/1W7hWgixyClz1WCJ0wfbP5A
提取码:c1ki
–来自百度网盘超级会员V6的分享

阅读全文 »

深入理解JVM - 分代的基本概念

目录

[TOC]

前言

​ 本次讲述jvm分代模型的基础概念,这个专栏会由浅入深的不断构建起来,循序渐进,和上一篇一样,是非常基础的内容

​ 其实这一篇才是对象分配的内容:深入理解JVM虚拟机 - jvm的对象分配策略 会发现里面有很多东西需要消化,而这一篇会讲一些基础的内容。

概述:

  1. 讲述JVM的基础分代模型以及版本升级的处理。
  2. 对象分配的基础概念和知识。
  3. 长期存活的对象是如何躲过垃圾回收进入到老年代
  4. jvm内存的核心参数解释以及基础配置
阅读全文 »

《六项思考帽》读书笔记

前言

​ 废话不多说,直接进入主题,这本书的作者挺有名的,但是这本书在豆瓣只有6.9的评分。不知道是不是翻译的问题还是作者,这本书本身写的过于入门。

阅读全文 »

《OKR工作法》读书笔记

前言

​ 这本书是逛多多用算法给我推的一本书,看封面挺有意思就买了下来,但是粗略下来发现这个工作法和TDD开发驱动模式一样指导意义大于实际意义,特别是在国内这种环境下这种工作模式可能只适合刚刚创业的公司尝试推行。而这本书好巧不巧就是讲了一个创业公司推进这个工作法的故事。

阅读全文 »