GC调优
如何确定垃圾对象 引用计数 无法排除对象的相互引用 枚举根节点,做可达性分析——JAVA目前使用的垃圾回收思想 根节点:类加载器、Thread 、虚拟机栈的本地变量表、static成员、常量引用、本地方法栈的变量等等 垃圾回收的算法 标记清除:效率不高,标记和清除两个过程的效率都不高,产生碎片,碎片太多会导致提前GC 复制: 实现简单,运行高效,但是空间利用率较低---YOUNG区所使用的 标记整理:没有了内存碎片,但是整理内存比较耗时 分带垃圾回收---目前JVM所使用的 Young区用复制算法 Old区用标记清除或者标记整理 对象分配 对象优先在Eden区分配 大对象直接进入老年代:-XX:PretenureSizeThreshold(超过该参数指定的大小,即为大对象) 长期存活的对象将进入老年代:对象晋升老年代的年龄阈值,可以通过参数-XX:MaxTenuringThreshold设置。 另外两种方法: -XX:TargetSurvivorRatio:设置ygc之后存活对象比例,比方说80%,之后计算这80%对象的平均年龄,之后平均年龄和PretenureSizeThreshold值取一个最小值,如果有对象达到这个最小值,则晋升到Old区 -XX:PrintTenuringDistribution:发生YGC之后,打印下存活对象的年龄分布情况 参考:https://www.jianshu.com/p/fa3569127416 垃圾收集器 垃圾器种类: 串行收集器Serial: Serial 、 Serial Old 并行收集器Parallel: Parallel Scavenge 、 Parallel Old ---吞吐量优先 并发收集器Concurrent:CMS 、 G1 ---停顿时间优先 参考:https://blog.csdn.net/tjiyu/article/details/53983650 停顿时间: 垃圾收集器做垃圾回收时中断应用执行时间 -XX:MaxGCPauseMillis 最大停顿时间 吞吐量: 花在垃圾收集时间和花在应用时间的占比 -XX:GCTimeRatio=<n>,垃圾收集时间占比:1/(1+n) eg:n=19 则垃圾收集时间占用5% 设置方法: 串行收集器:-XX:+UseSerialGC -XX:+UseSerialOldGC 设置第一个参数后,默认启用第二个参数 并行收集器:-XX:+UseParallelGC , -XX:+UseParallelOldGC 设置第一个参数后,默认启用第二个参数 Server模式下默认收集器 CMS:-XX:+UseConcMarkSweepGC -XX:UseParNewGC 设置第一个参数后,默认启用第二个参数 G1:-XX:+UseG1GC 参考:http://www.importnew.com/13827.html http://ifeve.com/useful-jvm-flags-part-7-cms-collector/ 验证启用垃圾收集器的类型的方法 jinfo -flag UseParallelGC 84231 jinfo -flag UseParallelOldGC 84231 jinfo -flag UseConcMarkSweepGc 84231 jinfo -flag UseG1GC 84231 并行和并发收集器的适用场景 并行:适合科学计算,后台处理等弱交互场景 并发:对响应时间有要求的场景,比如WEB 如何选择垃圾收集器 选择垃圾收集器的指导规则 优先调整堆的大小让服务器自己选择 如果内存小于100M,使用串行收集器 如果是单核,并且没有停顿时间的要求,串行或者JVM自己选 如果允许停顿时间超过1S,选择并行或者JVM自己选 如果响应时间最重要,并且不能超过1S,使用并发收集器 UseParallel Collector -XX:+UseParallelGC 手动开启,Server默认开启 -XX:ParallelGCThreads=<N> 多少个GC线程 CPU>8 开启N=5/8 CPU=8 开启N=CPU UseParallel Collector Ergonomics 并行收集器有自适应的特性 -XX:MaxGCPauseMillis=<N> 最大停顿时间 -XX:GCTimeRatio=<N> 吞吐量 -Xmx<N> 最大堆的大小 动态内存调整 自适应的内存调整参数 -XX:YoungGenerationSizeIncrement=<Y> 默认值20% Young区自增参数 -XX:TenuredGenerationSizeIncrement=<T> 默认值20% Old区自增参数 -XX:AdaptiveSizeDecrementScaleFactor=<D>默认值4% 自减参数 CMS Collector 并发收集 低停顿、低延迟 老年代收集器 CMS垃圾收集过程 CMS initial mark:初始标记 STW(stopTheWorld) CMS concurrent mark:并发标记 CMS-concurrent-preclean:并发预清理 CMS remark:重新标记 STW CMS concurrent sweep:并发清除 CMS-concurrent-reset:并发重置 CMS缺点 CPU敏感 浮动垃圾 空间碎片 CMS相关参数 -XX:ConcGCThreads: 并发的GC线程数 与应用程序并发执行时,GC的并发线程数,并非STW时的线程数 -XX:+UseCMSCompactAtFullCollection: FullGC之后做压缩 主要作用是为了减少内存碎片 -XX:CMSFullGCsBeforeCompaction: 多少次FullGC之后压缩一次 压缩是比较耗时的,所以并不是每次FullGC后都会进行压缩 -XX:CMSInitiatingOccupancyFraction: 触发FullGC Old区占有多少存活对象时触发FullGC 默认是92% -XX:+UseCMSInitiatingOccupancyOnly: 是否动态可调 -XX:+CMSScavengeBeforeRemark: FullGC之前先做YGC 一般调优时,会打开此参数 -XX:+CMSClassUnloadingEnabled: 启用回收Perm区 JDK7之前有Perm区 iCMS Incremental CMS 增量的CMS JDK8已废弃 适用于单核 双核 G1 Collector 大内存 优先的延迟 6G+ <0.5s G1的几个概念 Region SATB:Snapshot-At-The-Beginning,它是通过Root Tracing得到的,GC开始时存活对象的快照 后面GC回收以此为基础 RSet:记录了其他Region中的对象引用本Region中的对象的关系,属于points-into结构(谁引用了我的对象) YoungGC 新对象进入Eden区 发生YGC之后,存活对象拷贝到Survivor区 存活时间到达年龄阈值时,对象晋升到Old区 MixedGC 无fullGC,新增MixedGC MixedGC不是FullGC,动作是回收所以Young和部分Old global concurrent marking 全局并发标记 global concurrent marking Initial marking phase: 标记GC Root STW Root region scanning phase: 标记存活region Concurrent marking phase: 标记存活的对象 Remark phase: 重新标记 STW Cleanup phase: 部分STW MixedGC时机 InitiatingHeapOccupancyPercent: 堆占有率达到这个数值则触发global concurrent marking,默认45% G1HeapWastePercent: 在global concurrent marking结束之后,可以知道区有多少空间要被回收,在每次YGC之后和再次发生MixedGC之前,会检查垃圾占比是否达到此参数,只要达到了,下次才会发生MixedGC. G1MixedGCLiveThresholdPercent: Old区的region被回收时候存活对象占比 G1MixedGCCountTarget: 一次global concurrent marking之后,最多执行MixedGC的次数 G1OldSetRegionThresholdPercent: 一次Mixed GC中被选入CSet的最多Old区的region数量 一次MixedGC最多回收多少Old区的region 常用参数 -XX:+UseG1GC 开启G1 -XX:G1HeapRegionSize=<n> region的大小 1-32M 最多不能超过2048个 设置每个Region大小,范围1MB到32MB;目标是在最小Java堆时可以拥有约2048个Region; -XX:MaxGCPauseMillis 为G1设置暂停时间目标,默认值为200毫秒 -XX:G1NewSizePercent -XX:G1MaxNewSizePercent -XX:G1ReservePercent=10 保留防止to space溢出 默认10% -XX:ParallelGCThreads=n STW线程数 需要停止应用程序 -XX:ConcGCThreads=n 并发线程数=1/4*并行 最佳实现 年轻代大小:避免使用-Xmn -XX:NewRatio等显式设置Young区大小,会覆盖暂停时间目标 暂停时间目标:暂停时间不要太严苛,其吞吐量目标是90%的应用程序时间和10%的垃圾回收时间,太严苛会直接影响吞吐量 另外的知识点: https://blog.csdn.net/lovewebeye/article/details/80911838 -XX:newSize:表示新生代初始内存的大小,应该小于-Xms的值; -XX:MaxnewSize:表示新生代可被分配的内存的最大上限;当然这个值应该小于-Xmx的值; -Xmn:至于这个参数则是对 -XX:newSize、-XX:MaxnewSize两个参数的同时配置,也就是说如果通过-Xmn来配置新生代的内存大小,那么-XX:newSize = -XX:MaxnewSize = -Xmn,虽然会很方便,但需要注意的是这个参数是在JDK1.4版本以后才使用的。 是否需要切换到G1 50%以上的堆被存活的对象占用 查看命令是jmap -heap 86624 对象分配和晋升的速度变化非常大 垃圾回收时间特别长,超过了1秒 可视化GC日志分析工具 评价一个垃圾收集器是否好坏的指标:吞吐量 响应时间 同样进行调优 也就是要调这两个值 我们主要通过GC日志得到这两个值 打印日志相关参数 -XX:+PrintGCDetails 打印GC详细信息 -XX:+PrintGCTimeStamps 输出GC的时间戳(以基准时间的形式) -XX:+PrintGCDateStamps 输出GC的时间戳(以日期的形式,如 2013-05-04T21:53:59.234+0800) -Xloggc:$CATALINA_HOME/logs/gc.log -XX:+PrintHeapAtGC 发生GC时,打印整个堆的使用情况 -XX:+PrintTenuringDistribution 发生YGC之后,打印下存活对象的年龄分布情况 ParallelGC日志格式 GC调优步骤 打印GC日志 根据日志得到关键性能指标 分析GC原因,调优JVM参数 初始参数---获取gc日志 -XX:+DisableExplicitGC -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/data/logs/gclog/tomcat8180_DumpOnOutOfMemoryError.log -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps -Xloggc:/data/logs/gclog/tomcat8180-gc.log -XX:+PrintHeapAtGC -XX:+PrintTenuringDistribution -XX:+DisableExplicitGC 禁用掉明确的GC 禁用代码中的手动GC调用 -XX:+HeapDumpOnOutOfMemoryError 当发生内存溢出时,打印内存映像 -XX:HeapDumpPath=$CATALINA_HOME/logs/ -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps -Xloggc:$CATALINA_HOME/logs/gc.log 常用参数 -XX:+UseCompressedOops -XX:+UseCompressedClassPointers Parallel GC调优原则 除非确定,否则不要设置最大堆内存 优先设置吞吐量目标 如果吞吐量不达标,调大最大内存,不能让OS使用Swap,如果仍然达不到,减低目标 吞吐量能达到,GC时间太长,设置停顿时间目标 ParallelGC调优 设置Metaspace大小 -XX:MetaspaceSize=64M -XX:MaxMetaspaceSize=64M 添加吞吐量和停顿时间参数 -XX:GCTimeRatio=99 -XX:MaxGCPauseMillis=100 修改动态扩容增量 -XX:YoungGenerationSizeIncrement=30 默认值20%,现修改为30% G1 GC最佳实践 年轻代大小:避免使用-Xmn / -XX:NewRatio等显式设置Young区大小,会覆盖暂停时间目标。 暂停时间目标:暂停时间不要太苛刻,其吞吐量目标是90%的应用程序时间和10%的垃圾回收时间,太严苛会直接影响到吞吐量。 关于MixGC调优 -XX:InitiatingHeapOccupancyPercent -XX:G1MixedGCLiveThresholdPercent -XX:G1HeapWastePercent -XX:G1MixedGCCountTarget -XX:G1OldCSetRegionThresholdPercent G1调优相关参数 -XX:+UseG1GC -Xms128M -Xmx128M -XX:MetaspaceSize=64M -XX:MaxGCPauseMillis=100 -XX:+UseStringDeduplication -XX:StringDeduplicationAgeThreshold=3 并行垃圾收集器是吞吐量优先 并发垃圾收集器是停顿时间优先
参考: