工欲善其事必先利其器,何不给IDEA来一次调优呢?

前言

最近在读周志明大大的《深入理解Java 虚拟机》,看到大大对ecplise进行调优,手痒痒,想着亲手给自己的IDEA也做一次调优,正好最近电脑升级了一次内存,之前的配置肯定也不适合了,废话不多说,直接开搞!

环境介绍

IDEA:2019.1.3 64位(安装在固态盘)

JDK:1.8 64位

内存大小:16GB

使用软件:Java VisualVM,jstat ,jps

不要直接复制最后的配置,每台机器和环境都不一样,直接复制不能起到调优的效果,反而有可能起到反作用!!!!

启动时间计算标准:测试使用同一个SSM的Web项目,启动时间从双击到IDEA验证完项目中的Spring 配置为止

因为IDEA安装插件会影响启动速度,列举一下已安装的插件

image-20200813090638244

image-20200813090700911

优化前

IDEA初始配置

-Xms128m
-Xmx750m
-XX:ReservedCodeCacheSize=240m
-XX:+UseConcMarkSweepGC
-XX:SoftRefLRUPolicyMSPerMB=50
-ea
-Dsun.io.useCanonCaches=false
-Djava.net.preferIPv4Stack=true
-Djdk.http.auth.tunneling.disabledSchemes=""
-XX:+HeapDumpOnOutOfMemoryError
-XX:-OmitStackTraceInFastThrow

image-20200813091338532

统计:

  • 启动时间:62s
  • Minor GC:75次 耗时1.006s
  • Full GC:12次 耗时0.535s

分析

首先Minor GC,和Full GC次数有点太多了,Minor GC次数多的原因主要就是Eden区过小,反正内存16GB肯定够用了,干脆就给他分配2GB看看效果,至于Full GC,引发的原因有很多种,稍后再分析讨论

第一次优化

-Xms2048m
-Xmx2048m
-Xmn768m
-XX:ReservedCodeCacheSize=240m
-XX:+UseConcMarkSweepGC
-XX:SoftRefLRUPolicyMSPerMB=50
-ea
-Dsun.io.useCanonCaches=false
-Djava.net.preferIPv4Stack=true
-Djdk.http.auth.tunneling.disabledSchemes=""
-XX:+HeapDumpOnOutOfMemoryError
-XX:-OmitStackTraceInFastThrow

这次优化配置将初始堆大小变为2GB,最大堆大小也变为2GB,新生代的堆大小初始为768MB

image-20200813092437538

image-20200813092423195

统计

  • 启动时间:42.25s

  • Minor GC:5次 耗时0.48s

  • Full GC:6次 耗时0.42s

分析

Minor GC的次数已经算是很正常了,但是Full GC的次数好像还是有点多,但是从图中可以看出,Old区并没有存储多少东西,这里使用jstat查看一下发生GC的原因

image-20200813093803454

可以看到引发Full GC 的原因是由于元空间不足发生了扩容引起的,那么下一步优化的思路应该就从元空间入手了

第二次优化

-Xms2048m
-Xmx2048m
-Xmn768m
-XX:ReservedCodeCacheSize=240m
-XX:+UseConcMarkSweepGC
-XX:SoftRefLRUPolicyMSPerMB=50
-ea
-Dsun.io.useCanonCaches=false
-Djava.net.preferIPv4Stack=true
-Djdk.http.auth.tunneling.disabledSchemes=""
-XX:+HeapDumpOnOutOfMemoryError
-XX:-OmitStackTraceInFastThrow
-XX:MetaspaceSize=512m

这次使用-XX:MetaspaceSize参数,将元空间的初始大小改大一些

image-20200813094244942

image-20200813094236270

统计

  • 启动时间:39s

  • Minor GC:4次 耗时0.4s

  • Full GC:1次 耗时0.8s

分析

这次Full GC 只发生了一次,为什么还发生一次,元空间的大小应该是足够了呀!!!本着一次都不能忍的原则,再次使用jstat查看一次引发GC的原因

image-20200813094658127

发现目标,是IDEA启动时代码中使用 System.gc() 触发了这一次的Full GC,我们空间是完全足够的,所以这次Full GC是完全没必要的。干掉它

第三次优化

-Xms2048m
-Xmx2048m
-Xmn768m
-XX:ReservedCodeCacheSize=240m
-XX:+UseConcMarkSweepGC
-XX:SoftRefLRUPolicyMSPerMB=50
-ea
-Dsun.io.useCanonCaches=false
-Djava.net.preferIPv4Stack=true
-Djdk.http.auth.tunneling.disabledSchemes=""
-XX:+HeapDumpOnOutOfMemoryError
-XX:-OmitStackTraceInFastThrow
-XX:MetaspaceSize=512m
-XX:+DisableExplicitGC

这里使用-XX:+DisableExplicitGC参数,将代码中的System.gc()触发的GC给禁用掉,再次看看效果

image-20200813095055671

统计

  • 启动时间:38s

  • Minor GC:5次 耗时0.5s

  • Full GC:0次 耗时 0s

分析

虽然只是优化了1s,但是没有发生Full GC 就很舒服了,好像垃圾收集方面没啥可以搞得了,将目标转向上面的类加载时间,这玩意长,搞他肯定合理,先看一下搞之前的类加载时间

image-20200813100854577

第四次优化

-Xms2048m
-Xmx2048m
-Xmn768m
-XX:ReservedCodeCacheSize=240m
-XX:+UseConcMarkSweepGC
-XX:SoftRefLRUPolicyMSPerMB=50
-ea
-Dsun.io.useCanonCaches=false
-Djava.net.preferIPv4Stack=true
-Djdk.http.auth.tunneling.disabledSchemes=""
-XX:+HeapDumpOnOutOfMemoryError
-XX:-OmitStackTraceInFastThrow
-XX:MetaspaceSize=512m
-XX:+DisableExplicitGC
-Xverify:none

这个优化吧,诚实的讲完全是周大大书上说的,我自己是想不到的,他说是JDK6之后添加的类型检查验证器会影响到以前的类型检查验证器的工作,他调优的是Ecplise,说由于使用人数多,编译代码可以认为肯定是安全可靠的,因此没必要进行字节码验证。狗头一下,那我就说IDEA使用人数甚多,也是很没必要的,咱也禁用(禁用参数 -Xverify:none)

image-20200813101404765

统计

  • 启动时间:35s

  • Minor GC:5次 耗时0.5s

  • Full GC:0次 耗时 0s

分析

事实证明,禁用掉确实很合理,类加载时间从58s优化到46s,到此好像也没啥优化的了,于是我有去网上找了一下可以优化的点,由于没给我带来啥明显的提升,所以就放到一起写了

倒数第一次优化

-Xms2048m
-Xmx2048m
-Xmn768m
-XX:ReservedCodeCacheSize=240m
-XX:+UseConcMarkSweepGC
-XX:SoftRefLRUPolicyMSPerMB=50
-ea
-Dsun.io.useCanonCaches=false
-Djava.net.preferIPv4Stack=true
-Djdk.http.auth.tunneling.disabledSchemes=""
-XX:+HeapDumpOnOutOfMemoryError
-XX:-OmitStackTraceInFastThrow
-XX:MetaspaceSize=512m
-XX:+DisableExplicitGC
-Xverify:none
-XX:+UseNUMA
-Xnoclassgc
-XX:CMSInitiatingOccupancyFraction=75
-XX:CMSFullGCsBeforeCompaction=3

-Xnoclassgc:禁用掉JVM的类的垃圾回收

-XX:+UseNUMA:这个说起来比较复杂,有兴趣参考链接

-XX:CMSInitiatingOccupancyFraction=75:当老年代容量使用到75%时就触发Full GC,默认是92%,因为这里我们使用的是ParNew + CMS的垃圾收集器组合,到达92%再进行清理容易引起CMS由于没有足够的空余位置协助清理造成并发失败,然后会冻结用户的线程(IDEA长时间卡顿的原因),去使用古老的Serial Old收集器(单线程的哦)进行收集。

-XX:CMSFullGCsBeforeCompaction=3:CMS 是基于标记清除的算法,意味着会产生很多空间碎片,这个参数就是指定发生多少次Full GC对空间做一次压缩整理,默认是0,即每次都整理,有点浪费时间

image-20200813104050793

统计

  • 启动时间:34s

  • Minor GC:4次 耗时0.38s

  • Full GC:0次 耗时 0s

分析

通过启动速度可以看出,上面设置的参数对于启动速度的优化没有多大的提升,这是很正常的,他们的价值还将会体现在IDEA长时间使用的时候。

Q&A

为什么不使用G1收集器?

其实我背地里悄悄的用了,上面最后一次配置,我将CMS换为G1后,时间又长了。。。我的理解应该是G1复杂的记忆集和对写屏障的复杂操作,使得G1消耗更多的计算资源和内存资源,在2GB的内存大小下,与CMS相比并不占优势,在更大的内存下G1的优势才能彻底发挥出来,所以我从一开始就没考虑过G1,一直是针对CMS进行的优化,上面的优化参数也仅仅是针对我电脑下CMS垃圾收集器优化的,如果你想使用G1,按照参考这个思路,针对G1去做一次优化。(纯属个人见解,错误之处请指正)

Java VisualVM、jstat、jps在哪?

jstat、jps 安装完jdk并配置好环境变量后就可以在终端中直接使用,命令形式如上面截图。

Java VisualVM 在jdk根目录的bin文件夹下,如果没有,说明你的jdk版本比较新(起码jdk8后面的了),需要单独去下载

我的 Java VisualVM 连接上后为什么没有你那么多功能?

我的是安装完所有的插件,安装位置工具--插件--可用插件,安装比较慢的(你懂得,科学一下)

image-20200813112242837

还有优化点吗?

有,肯定有。首先肯定是电脑性能问题,这个需要靠钱解决。其次,固态盘比较大的可以考虑放在固态盘中,提升很明显。还有每次JDK、IDEA新版本的发布都会不仅仅是发布新功能,肯定也会有性能的提升,可以考虑换一下新的版本。至于参数的优化方面,肯定是也还有,这能说我这参数达到的我优化的目的,肯定不是最好的,剩下的调优交给时间吧!

这些IDEA的配置要写在那个配置文件中?

我是直接在IDEA中修改的,位置如下:

image-20200813113323681

我在IDEA中改完配置后启动不了了怎么办?

首先,在修改的时候最好是一个参数一个参数的修改或者添加,如果发生参数拼写出错,设置不合理,格式不对,或者参数冲突都会造成IDEA无法启动,这时候你可以去下面两个位置找一下IDEA的配置文件,将最后一次的参数改掉就可以启动了

位置1:IDEA的安装目录bin文件夹下(32位的找上面配置文件,64位的找下面的配置文件)

image-20200813113701649

如果发现这两个配置文件中的配置信息都不是你最近改的配置,说明你的IDEA使用的配置文件并不是这里的

请找位置2:C盘--用户(Users)--你的用户名--idea用户配置文件夹--config目录

image-20200813114041469

posted @ 2020-08-13 11:53  UtilMan  阅读(363)  评论(0编辑  收藏  举报