前言:

我们知道,IDEA是用Java写的,那么他肯定也存在虚拟机的调优的问题,那么今天我们就对它进行开刀。

下面是默认参数 位置在:C:\Program Files\JetBrains\IntelliJ IDEA 2018.2\bin\idea64.exe.vmoptions

 -Xms128m
-Xmx756m
-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

我们从这里可以看到,堆最小分配了128M,最大分配了756M。

新生代用的是ParNew收集器,基于标记复制算法

老年代用的是CMS,基于标记清除算法。

优化前:

我们这里用到了两个神器。jvisualvm.exe和jconsole.exe。

我们先启动一下IDEA

新生代进行了56次gc,老年代进行了5次Full gc。这肯定不能忍受的嘛。

优化一:

 1 -Xms1024m
2 -Xmx1024m
3 -Xmn350m
-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 14 -verbose:gc
15 -XX:+PrintGCDetails
16 -XX:+PrintGCDateStamps
17 -Xloggc:gcc.log

设置堆的最大最小都为1024M,不给动态扩容。并且设置新生代为350M,同时打出日志。

可以看到,只进行了7次新生代GC,3次老年代GC。

我很奇怪,为何老年代没有填满,并且还有好多空间,会发生三次FullGC呢?部分日志如下:

 2018-08-20T22:35:57.399+0800: 3.963: [CMS-concurrent-preclean-start]
2018-08-20T22:35:57.399+0800: 3.965: [CMS-concurrent-preclean: 0.002/0.002 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
2018-08-20T22:35:57.399+0800: 3.965: [CMS-concurrent-abortable-preclean-start]
2018-08-20T22:35:59.457+0800: 6.018: [CMS-concurrent-abortable-preclean: 1.465/2.053 secs] [Times: user=6.16 sys=0.52, real=2.06 secs]
2018-08-20T22:35:59.458+0800: 6.019: [GC (CMS Final Remark) [YG occupancy: 167766 K (322560 K)]2018-08-20T22:35:59.458+0800: 6.019: [Rescan (parallel) , 0.0669837 secs]2018-08-20T22:35:59.525+0800: 6.086: [weak refs processing, 0.0000425 secs]2018-08-20T22:35:59.525+0800: 6.086: [class unloading, 0.0054995 secs]2018-08-20T22:35:59.530+0800: 6.091: [scrub symbol table, 0.0064731 secs]2018-08-20T22:35:59.537+0800: 6.098: [scrub string table, 0.0004637 secs][1 CMS-remark: 0K(690176K)] 167766K(1012736K), 0.0803359 secs] [Times: user=0.25 sys=0.00, real=0.08 secs]
2018-08-20T22:35:59.538+0800: 6.099: [CMS-concurrent-sweep-start]
2018-08-20T22:35:59.538+0800: 6.099: [CMS-concurrent-sweep: 0.000/0.000 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
2018-08-20T22:35:59.538+0800: 6.099: [CMS-concurrent-reset-start]
2018-08-20T22:35:59.540+0800: 6.101: [CMS-concurrent-reset: 0.002/0.002 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
2018-08-20T22:36:03.352+0800: 9.915: [GC (Allocation Failure) 2018-08-20T22:36:03.352+0800: 9.915: [ParNew: 310560K->29155K(322560K), 0.0792661 secs] 310560K->47946K(1012736K), 0.0793506 secs] [Times: user=0.25 sys=0.02, real=0.08 secs]
2018-08-20T22:36:07.438+0800: 14.013: [GC (CMS Initial Mark) [1 CMS-initial-mark: 18790K(690176K)] 255956K(1012736K), 0.0418642 secs] [Times: user=0.22 sys=0.00, real=0.06 secs]
2018-08-20T22:36:07.515+0800: 14.076: [CMS-concurrent-mark-start]

因为老年代是采用CMS,我们来分析下,什么情况下CMS会导致FullGC。

1:担保失败,即在并发清除,会有新生代担保进来,如果不足,则提前出发Full GC。

可通过 -XX:CMSInitiatingOccupancyFraction 来调整比例。

2:因为CMS是标记清除算法,势必会产生大量的碎片,导致Full GC

可通过调整老年代的大小来进行避免。

但经过上面两个分析,并进行了调整,发觉仍然会发生FullGC,并且老年代的空间还剩余特别的多,根本不存在空间不足,或者找不到连续空间的问题,那么为何还会进行Full GC呢。

优化二:

 -Xms1024m
-Xmx1024m
-Xmn350m
-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 -verbose:gc
-XX:+PrintGCDetails
-XX:+PrintGCDateStamps
-Xloggc:gcc.log 19 -XX:MetaspaceSize=1024m

注意看最后一个参数-XX:MetaspaceSize=1024M

可以看到,此时一次FullGC都没有发生,新生代GC至发生了7次就已经完成了启动。

结论:

测试,我测试了好多遍,当然不会像博客这样简单的测试。差了好多资料,比了好多的数据。

优化前,大概启动进行50多次新生代GC,3-5次老年代GC。

优化后,进行7次左右新生代GC,0次老年代GC。

启动时间大概快了有10s。

分析一下为何,MetaSpaceGC 会引发一次CMS GC

 JDK8: Metaspace
In JDK 8, classes metadata is now stored in the native heap
and this space is called Metaspace. There are some new flags added for
Metaspace in JDK 8:
-XX:MetaspaceSize= where is the initial amount of space(the initial
high-water-mark) allocated for class metadata (in bytes) that may induce a
garbage collection to unload classes. The amount is approximate. After the
high-water-mark is first reached, the next high-water-mark is managed by
the garbage collector
-XX:MaxMetaspaceSize= where is the maximum amount of space to be allocated for class
metadata (in bytes). This flag can be used to limit the amount of space
allocated for class metadata. This value is approximate. By default there
is no limit set.
-XX:MinMetaspaceFreeRatio= where is the minimum percentage of class metadata capacity
free after a GC to avoid an increase in the amount of space
(high-water-mark) allocated for class metadata that will induce a garbage collection.
-XX:MaxMetaspaceFreeRatio= where is the maximum percentage of class metadata capacity
free after a GC to avoid a reduction in the amount of space
(high-water-mark) allocated for class metadata that will induce a garbage collection.
By default class
metadata allocation is only limited by the amount of available native memory. We
can use the new option MaxMetaspaceSize to limit the amount of native memory
used for the class metadata. It is analogous(类似) to MaxPermSize. A garbage collection is induced to collect the dead classloaders
and classes when the class metadata usage reaches MetaspaceSize (12Mbytes on
the 32bit client VM and 16Mbytes on the 32bit server VM with larger sizes on
the 64bit VMs). Set MetaspaceSize to a higher value to delay the induced
garbage collections. After an induced garbage collection, the class metadata usage
needed to induce the next garbage collection may be increased.

JVM规范中运行时数据区域中的方法区,在HotSpot虚拟机中又被习惯称为永生代或者永生区,Permanet Generation中存放的为一些class的信息、常量、静态变量等数据,当系统中要加载的类、反射的类和调用的方法较多时,Permanet Generation可能会被占满,在未配置为采用CMS GC的情况下也会执行Full GC。如果经过Full GC仍然回收不了,那么JVM会抛出如下错误信息:java.lang.OutOfMemoryError: PermGen space 为避免Perm Gen占满造成Full GC现象,可采用的方法为增大Perm Gen空间或转为使用CMS GC。

即如果MetaSpace不足,也会触发Full GC(在64为机器上默认20.8M)。那么调大即可,延迟Full GC的时间。

参考资料:

https://blog.csdn.net/liubenlong007/article/details/78143285

http://tech.dianwoda.com/2018/01/10/jdk8-de-fullgc-zhi-metaspace/

记一次IDEA编译器调优的更多相关文章

  1. 记一次单机Nginx调优,效果立竿见影

    一.物理环境 1.系统是Centos 8,系统配置 2核4G,8M带宽,一台很轻的应用服务器. 2.站点部署情况.但站点部署两个实例,占用两个端口,使用nginx 负载转发到这两个web站点.  二. ...

  2. [MYSQL] 记一次MySQL性能调优

    最近在做数据迁移工作,已有一堆数据文件,要把这些数据文件写到MySQL 数据库里面去. MySQL数据库上架了一层服务接口,可以直接调用.博主写了一个迁移程序,放在服务器A上. *********** ...

  3. 记一次GreenPlum性能调优

    在部署了的GreenPlum集群中进行数据查询时,发现数据量一旦大了,查询一跑就中断,提示某个segment中断了连接. ERROR 58M01 "Error on receive from ...

  4. 记一次idea性能调优

    因自研的自动化测试工具包含压测功能,在自己本地代码开发完毕后进行测试,对目标接口进行1000次访问,发现idea在执行结束后变的异常卡顿,怀疑是idea工具或者程序代码存在问题,遂进行排查. ---- ...

  5. 记一次数据库调优过程(IIS发过来SQLSERVER 的FETCH API_CURSOR语句是神马?)

    记一次数据库调优过程(IIS发过来SQLSERVER 的FETCH API_CURSOR语句是神马?) 前几天帮客户优化一个数据库,那个数据库的大小是6G 这麽小的数据库按道理不会有太大的性能问题的, ...

  6. Spark踩坑记:Spark Streaming+kafka应用及调优

    前言 在WeTest舆情项目中,需要对每天千万级的游戏评论信息进行词频统计,在生产者一端,我们将数据按照每天的拉取时间存入了Kafka当中,而在消费者一端,我们利用了spark streaming从k ...

  7. 记Oracle中regexp_substr的一次调优(速度提高95.5%)

    项目中需要做一个船舶代理费的功能,针对代理的船进行收费,那么该功能的第一步便是选择进行代理费用信息的录入,在进行船舶选择的时候,发现加载相关船舶信息十分的慢,其主要在sql语句的执行,因为测试的时候数 ...

  8. 记一次Web服务的性能调优

    前言 一个项目在经历开发.测试.上线后,当时的用户规模还比较小,所以刚刚上线的项目一般会表现稳定.但是随着时间的推移,用户数量的增加,qps的增加等因素会造成项目慢慢表现出网页半天无响应的状况.在之前 ...

  9. 记一次sql server 性能调优,查询从20秒至2秒

    一.需求 需求很简单,就是需要查询一个报表,只有1个表,数据量大约60万左右,但是中间有些逻辑. 先说明一下服务器配置情况:1核CPU.2GB内存.机械硬盘.Sqlserver 2008 R2.Win ...

随机推荐

  1. 学习Tensorflow的LSTM的RNN例子

    学习Tensorflow的LSTM的RNN例子 基于TensorFlow一次简单的RNN实现 极客学院-递归神经网络 如何使用TensorFlow构建.训练和改进循环神经网络

  2. 综合数据api接口使用

    由于请求数据接口是跨域的,但是我们无法改变接口的代码 先从请求后台,然后从后台进行二次请求,请求数据接口 原生代码 package edu.nf.http.test; import org.apach ...

  3. java生成pdf文件 --- Table

    Java利用itext实现导出PDF文件 所需要的jar包:com.lowagie.text_2.1.7.v201004222200.jar jar包下载地址:http://cn.jarfire.or ...

  4. js中push和pop的用法

    push: 将新元素追加到一个数组中,并返回新的数组长度: 语法:arrayObj.push([item1 [item2 [. . . [itemN ]]]]) var number; var my_ ...

  5. 【python-appium】手机一直提示重新安装settings unlock 输入法等 注释掉以下代码

    注释掉目录:C:\Program Files (x86)\Appium\node_modules\appium\lib\devices\android\android.js this.initUnic ...

  6. git 命令(基础篇)的本质理解

    主要命令 1. 提交,git commit 本质:创建一个节点(node),标志了当前位置(node)与以前的node存在不同之处,如下图中的 c0 <-- c1 <-- c2 等等 图中 ...

  7. unable to load http://docbook.sourceforge.net/release/xsl/current/html/docbook.xsl

    问题:unable to load http://docbook.sourceforge.net/release/xsl/current/html/docbook.xsl 解决:yum -y inst ...

  8. document.domain实现不同域名跨域

    利用document.domain 实现跨域:前提条件:这两个域名必须属于同一个基础域名!而且所用的协议,端口都要一致,否则无法利用document.domain进行跨域. 两个子域名:aaa.xxx ...

  9. 常用的评价指标:accuracy、precision、recall、F1-score、ROC-AUC、PR-AUC

  10. tomcat容器是如何创建servlet类实例?用到了什么原理?

    当容器启动时,会读取在webapps目录下所有的web应用中的web.xml文件,然后对 xml文件进行解析,并读取servlet注册信息.然后,将每个应用中注册的servlet类都进行加载,并通过  ...