写点什么

JVM 性能调优实战:让你的 IntelliJ Idea 纵享丝滑

用户头像
Silently9527
关注
发布于: 2021 年 01 月 18 日
JVM性能调优实战:让你的IntelliJ Idea纵享丝滑

本文已被 Github 仓库收录 https://github.com/silently9527/JavaCore


微信公众号:贝塔学 Java


前言

在前面整理了一篇关于 JVM 故障诊断和处理工具,考虑到大部分的 Java 程序员都使用的时 IntelliJ Idea,本篇就使用工具来实战演练对 IntelliJ Idea 运行速度调优


调优前的运行状态


原始配置内容

要查询 idea 原始配置文件的路径可以在 VisualVM 中的概述中查看



原始配置内容:


-XX:ReservedCodeCacheSize=240m-XX:+UseCompressedOops-Dfile.encoding=UTF-8-XX:SoftRefLRUPolicyMSPerMB=50-ea-Dsun.io.useCanonCaches=false-Djava.net.preferIPv4Stack=true-Djdk.http.auth.tunneling.disabledSchemes=""-XX:+HeapDumpOnOutOfMemoryError-XX:-OmitStackTraceInFastThrow
-XX:ErrorFile=$USER_HOME/java_error_in_idea_%p.log-XX:HeapDumpPath=$USER_HOME/java_error_in_idea.hprof
-Xmx512m
复制代码


打印启动时间插件开发

需要直观的看到优化前和优化后启动时间的变化,所以需要简单做一个 Idea 的插件开发,关于 Idea 插件开发的流程建议参考我以前的文章《IDEA 插件:多线程文件下载插件开发


JVM 的启动时间到所有组件初始化完成后的时间就看做是 IDEA 的启动时间,代码如下


public class MyApplicationInitializedListener implements ApplicationInitializedListener {    @Override    public void componentsInitialized() {        RuntimeMXBean bean = ManagementFactory.getRuntimeMXBean();        long startTime = bean.getStartTime();        long costTime = System.currentTimeMillis() - startTime;
Messages.showMessageDialog("毫秒:" + costTime, "启动耗时", Messages.getInformationIcon()); }}
复制代码


plugin.xml 中添加如下代码:


<extensions defaultextensionns="com.intellij">    <applicationinitializedlistener id="MyApplicationInitializedListener" implementation="cn.silently9527.MyApplicationInitializedListener" /></extensions>
复制代码


优化前的启动信息与时间消耗



根据 VisualGC 和 IDEA 启动插件收集到的信息:

  • IDEA 启动耗时 15s

  • 总共垃圾收集 22 次,耗时 1.2s,其中新生代 GC 17 次,耗时 324ms; 老年代 GC 5 次,耗时 953ms

  • 加载类 27526 个,耗时 21s


&gt; 按照这个数据来看也算是正常,15s 其实也在接受范围内,由于本文主要演示性能调优,所以需要测试能否在快一些


开始尝试优化


调整内存来控制垃圾回收频率

图上我们可以看出,启动参数指定的 512m 的内存被分配到新生代的只有 169m,由于 IDEA 是我们开发常用的工具,平时的编译过程也需要足够的内存,所以我们需要先把总的内存扩大,这里我设置最大的内存-Xmx1024m,为了让 JVM 在 GC 期间不需要再浪费时间再动态计算扩容大小,同时也设置了-Xms1024m


在启动的过程中 Eden 共发生了 17 次 GC,为了减少新生代 gc 次数,我把新生代的内存大小设置成-Xmn256m;


重新启动之后查看 VisualGC,新生代 gc 次数从 17 次 降低到了 7 次,耗时从 324ms 降低到了 152ms。



在调整内存前发生了 5 次 Full GC,调整内存后的依然还是有 4 次 Full GC,但是从两张图我们可以看出,老年代的空间还有很多剩余,是不应该发生 Full GC 的;考虑是否是代码中有地方手动调用System.gc()出发了 Full GC,所以添加了参数-XX:+DisableExplicitGC,再次重新启动 IDEA,结果很失望,依然还有 4 次 Full GC;


再次仔细观察优化前的图,注意看 Last Cause: Metadata GC Threshold , 最后一次 gc 是应该 Metaspace 区域内存不够发生的 GC,为了验证我们的猜想,打印出 GC 日志来看看。在idea.vmoptions中添加打印日志相关的参数:


-XX:+PrintGCDetails-XX:+PrintGCDateStamps-Xloggc:../gc.log
复制代码


JVM 的 GC 日志的主要参数包括如下几个:

- -XX:+PrintGC 输出 GC 日志

- -XX:+PrintGCDetails 输出 GC 的详细日志

- -XX:+PrintGCTimeStamps 输出 GC 的时间戳(以基准时间的形式)

- -XX:+PrintGCDateStamps 输出 GC 的时间戳(以日期的形式,如 2013-05-04T21:53:59.234+0800)

- -XX:+PrintHeapAtGC 在进行 GC 的前后打印出堆的信息

- -Xloggc:../logs/gc.log 日志文件的输出路径


重新启动 idea,查看 gc.log



&gt; 其中PSYoungGen:表示新生代使用的 ParallelScavenge 垃圾收集器,31416K-&gt;0K(181248K)表示 gc 前已使用的内存大小 -&gt; gc 后已使用内存大小(该区域的总内存大小)


从日志中我们看出每次 Full GC 都是因为Metadata GC Threshold,而 Metaspace 每次 gc 回收的内存几乎没有,仅仅是扩大了该区域的容量;找到了原因那就好办了,添加如下的参数调整 Metaspace 的大小:


-XX:MetaspaceSize=256m
复制代码


再次重启 Idea 之后,发现 Full GC 没有了,心情很爽



测试打开大项目点击编译代码,发现自己的 idea 卡死了,查看 VisualGC 之后发现堆内存都还有空闲,只有 Metaspace 被全部占满了,所以是自己给的最大空间设置太小,所以直接去掉了-XX:MaxMetaspaceSize=256m


选择垃圾收集器

从刚才的 gc 日志中,我们可以发现默认使用的是 ParallelScavenge + Parallel Old 垃圾收集器,这个组合注重的是吞吐量,这里我们尝试换一个注重低延时的垃圾收集器试一试


  • ParNew + CMS

idea.vmoptions中添加如下配置:


-XX:+UseConcMarkSweepGC-XX:+UseParNewGC
复制代码


重启 IDEA 之后查看 VisualGC



很尴尬,同样发生了 6 次 gc,ParallelScavenge + Parallel Old的组合耗时 197ms,而ParNew + CMS的组合耗时 379ms;虽然是这个结果,但是我们需要考虑当前只发生了 MinorGC,如果发生 FullGC 了结果又会如何了,大家可以自己测试一下


  • G1

我们在换一个最新的 G1 垃圾回收器试试,在idea.vmoptions中添加如下配置:


-XX:+UseG1GC
复制代码



这个结果好像也还是要慢一点点,自己多次测试过这两个垃圾回收器,虽然每次结果都不一样,相差不远,所以垃圾回收器可以自己选择,这里我们选择的是 G1


类加载时间优化

根据之前的分析,idea 启动加载类 27526 个,耗时 21s,这个我们有办法能优化一下吗?因为 idea 是常用的开发工具,经常很多人的使用,我们可以认为它的代码是安全的,是否符合当前虚拟机的要求,不会危害虚拟机的安全,所以我们使用参数-Xverify:none来禁用字节码的验证过程


重启 IDEA



耗时下降到了 11s,效果还是比较明显的


总结


做完了所有优化之后,经过多次重启测试,平均的启动时间下降到了 11s,为了安慰我本次操作没有白辛苦,搞一张 11s 以下的图





写到最后(点关注,不迷路)

文中或许会存在或多或少的不足、错误之处,有建议或者意见也非常欢迎大家在评论交流。


最后,白嫖不好,创作不易,希望朋友们可以点赞评论关注三连,因为这些就是我分享的全部动力来源🙏



原创不易 转载请注明出处:https://silently9527.cn/archives/102



我已经从零开始手写了简易版 springmvc,以及编写了详细的说明文档,希望能够帮助伙伴们深入理解 springmvc 核心原理,有需要的朋友欢迎关注公众号:贝塔学 JAVA ,回复源码即可

>

>



欢迎关注公众号:贝塔学 JAVA



发布于: 2021 年 01 月 18 日阅读数: 29
用户头像

Silently9527

关注

公众号:贝塔学JAVA 2018.05.09 加入

Simple Programmer, Make the complex simple

评论

发布
暂无评论
JVM性能调优实战:让你的IntelliJ Idea纵享丝滑