赞
踩
由于从 JDK 8 到 JDK 11 特性变化太多,对于这样的性能下降问题,为了能快速有效的解决,我们做了如下的尝试。
3.1统一 JDK 8 和 JDK 11 的参数,验证效果
=============================
由于 JDK 11 和 JDK 8 实现变化很多,部分功能完全不同,但是这些变化的功能一般都有参数控制,一种有效的尝试:梳理 JDK 8 和 JDK 11 关于 G1 的参数,将它们设置为相同的值,比如关闭 IHOP 的自适应,关闭线程调整等。这里简单的给出 JDK 8 和 JDK 11 不同参数的比较,如下图所示:
将两者参数都设置为和 JDK 8 一样的值,重新验证测试,结果不变,JDK 11 性能仍然下降。
3.2GC日志分析,确定JDK 11性能下降点
=======================
对于 JDK 8 和 JDK 11 同时配置日志收集功能,重新测试,获得 GC 日志。通过 GC 日志分析,我们发现差异主要在 G1 young gc 的 object copy 阶段(耗时基本在这),JDK 11 的 Young GC 耗时大概 200ms,JDK 8 的 Young GC 耗时大概 100ms,两者设置的目标停顿时间都是 100ms。
JDK 11 中 GC 日志片段:
JDK 8中 GC 日志片段:
我们对整个日志做了统计,有以下发现:
并发标记时机不同,混合回收的时机也不同;
单次 GC 中对象复制的耗时不同,JDK 11 明显更长;
总体 GC 次数 JDK 11 得更多,包括了并发标记的停顿次数;
总体 GC 的耗时 JDK 11 更多。
针对 Young GC 的性能劣化,我们重点关注测试了和 Young GC 相关的参数,例如:调整
UseDynamicNumberOfGCThreads、G1UseAdaptiveIHOP 、GCTimeRatio 均没有效果。
下面我们尝试使用不同的工具来进一步定位到底哪里出了问题。
3.3JFR分析-确认日志分析结果
=================
毕昇 JDK 11和毕昇 JDK 8 都引入了 JFR,JFR 作为 JVM 中问题定位的新贵,我们也在该案例进行了尝试,关于JFR的原理和使用,参考本系列的技术文章:Java Flight Recorder - 事件机制详解。
3.3.1JDK 11总体信息
===============
JDK 8 中通过 JFR 收集信息。
3.3.2JDK 8总体信息
==============
JFR 的结论和我们前面分析的结论一致,JDK 11 中中断比例明显高于 JDK 8。
3.3.3JDK 11中垃圾回收发生的情况
=====================
3.3.4JDK 8中垃圾回收发生的情况
====================
从图中可以看到在 JDK 11 中应用消耗内存的速度更快(曲线速率更为陡峭),根据垃圾回收的原理,内存的消耗和分配相关。
3.3.5JDK 11中VM操作
================
3.3.6JDK 8中VM操作
===============
通过 JFR 整体的分析,得到的结论和我们前面的一致,确定了 Young GC 可能存在问题,但是没有更多的信息。
3.4火焰图-发现热点
===========
为了进一步的追踪 Young GC 里面到底发生了什么导致对象赋值更为耗时,我们使用Async-perf 进行了热点采集。关于火焰图的使用参考本系列的技术文章:使用 perf 解决 JDK8 小版本升级后性能下降的问题
3.4.1JDK 11的火焰图
===============
3.4.2JDK 11 GC部分火焰图
===================
3.4.3JDK 8的火焰图
==============
3.4.4JDK 8 GC部分火焰图
==================
通过分析火焰图,并比较 JDK 8 和 JDK 11 的差异,可以得到:
在 JDK 11 中,耗时主要在:
1)G1ParEvacuateFollowersClosure::do_void()
2)G1RemSet::scan_rem_set
在 JDK 8 中,耗时主要在:
1)G1ParEvacuateFollowersClosure::do_void()
下一步,我们对 JDK 11 里面新出现的 scan_rem_set() 进行更进一步分析,发现该函数仅仅和引用集相关,通过修改 RSet 相关参数(修改 G1ConcRefinementGreenZone ),将 RSet 的处理尽可能地从Young GC的操作中移除。火焰图中参数不再成为热点,但是 JDK 11 仍然性能下降。
比较 JDK 8 和 JDK 11 中
G1ParEvacuateFollowersClosure::do_void() 中的不同,除了数组处理外其他的基本没有变化,我们将 JDK 11 此处的代码修改和 JDK 8 完全一样,但是性能仍然下降。
结论:虽然
G1ParEvacuateFollowersClosure::do_void() 是性能下降的触发点,但是此处并不是问题的根因,应该是其他的原因造成了该函数调用次数增加或者耗时增加。
3.5逐个版本验证-最终确定问题
================
我们分析了所有可能的情况,仍然无法快速找到问题的根源,只能使用最笨的办法,逐个版本来验证从哪个版本开始性能下降。
在大量的验证中,对于 JDK 9、JDK 10,以及小版本等都重新做了构建(关于 JDK 的构建可以参考官网),我们发现 JDK 9-B74 和 JDK 9-B73 有一个明显的区别。为此我们分析了 JDK 9-B73 输入的代码。发现该代码和 PLAB 的设置相关,为此梳理了所有 PLAB 相关的变动:
B66 版本为了解决 PLAB size 获取不对的问题(根据 GC 线程数量动态调整,但是开启
UseDynamicNumberOfGCThreads 后该值有问题,默认是关闭)修复了 bug。具体见 jira:Determining the desired PLAB size adjusts to the the number of threads at the wrong place
B74 发现有问题(desired_plab_sz 可能会有相除截断问题和没有对齐的问题),重新修改,具体见 8079555: REDO - Determining the desired PLAB size adjusts to the the number of threads at the wrong place
B115 中发现 B74 的修改,动态调整 PLAB 大小后,会导致很多情况 PLAB 过小(大概就是不走 PLAB,走了直接分配),频繁的话会导致性能大幅下降,又做了修复 Net PLAB size is clipped to max PLAB size as a whole, not on a per thread basis
重新修改了代码,打印 PLAB 的大小。对比后发现 desired_plab_sz 大小,在性能正常的版本中该值为 1024 或者 4096(分别是 YoungPLAB 和 OLDPLAB),在性能下降的版本中该值为 258。由此确认 desired_plab_sz 不正确的计算导致了性能下降。
3.6PLAB 为什么会引起性能下降?
===================
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)
针对最近很多人都在面试,我这边也整理了相当多的面试专题资料,也有其他大厂的面经。希望可以帮助到大家。
上述的面试题答案都整理成文档笔记。 也还整理了一些面试资料&最新2021收集的一些大厂的面试真题(都整理成文档,小部分截图)
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
添加V获取:vip1024b (备注Java)**
[外链图片转存中…(img-frBWiFEq-1711922290555)]
针对最近很多人都在面试,我这边也整理了相当多的面试专题资料,也有其他大厂的面经。希望可以帮助到大家。
[外链图片转存中…(img-oUlfNguT-1711922290555)]
上述的面试题答案都整理成文档笔记。 也还整理了一些面试资料&最新2021收集的一些大厂的面试真题(都整理成文档,小部分截图)
[外链图片转存中…(img-8X3d7ECG-1711922290556)]
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。