前言:

我们知道,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. vue中的import、export、requre的区别

    在es6之前js一直没有自己的模块语法,为了解决这种尴尬就有了require.js的出现.在es6发布之后js又引入了import的概念使得不清楚两者之间的区别的同学在实际使用过程中造成了自己的误解, ...

  2. Linux下配置yum

    [一]用本地文件创建本地yum源 1. 创建iso存放目录和挂载目录 mkdir /mnt/iso mkdir /mnt/cdrom 2. 将iso镜像文件上传到/mnt/iso文件夹下 3. 将/m ...

  3. explain 类型分析

    all 全表扫描 ☆ index 索引全扫描 ☆☆ range 索引范围扫描,常用语<,<=,>=,between等操作 ☆☆☆ ref 使用非唯一索引扫描或唯一索引前缀扫描,返回单 ...

  4. qhfl-1 跨域

    CORS跨域请求 CORS即Cross Origin Resource Sharing 跨域资源共享,那么跨域请求还分为两种,一种叫简单请求,一种是复杂请求 简单请求 HTTP方法是下列方法之一 HE ...

  5. JAVA 8 主要新特性 ----------------(二)版本中数据结构的修改浅析

    一.版本中数据结构的修改浅析1.HashMap.HashSet.ConcurrentHashMap的数据结构发生变化 (1)HashMap简介(结构:哈希表+链表) HashMap存储的数据是无序的, ...

  6. docker知识点杂记

    最近重新梳理了一下docker的一些基本知识,简单做了下总结.以后会逐步补充. 1.查看系统内核版本,需要3.10以上 $ uname -r 2.下载docker 说明:centos安装docker比 ...

  7. POJ 1177Picture 扫描线(若干矩形叠加后周长)

    Picture   Description A number of rectangular posters, photographs and other pictures of the same sh ...

  8. 深圳scala-meetup-20180902(3)- Using heterogeneous Monads in for-comprehension with Monad Transformer

    scala中的Option类型是个很好用的数据结构,用None来替代java的null可以大大降低代码的复杂性,它还是一个更容易解释的状态表达形式,比如在读取数据时我们用Some(Row)来代表读取的 ...

  9. kaili 安装中文输入法

    kaili 安装中文输入法 更换为国内可用的源: vim /etc/apt/sources.list 添加以下内容: deb http://mirrors.ustc.edu.cn/kali sana ...

  10. Facebook的一些基本操作(网页版)

    前期准备 1,注册一次Facebook账号,新建一个应用取到应用id 2,引进Facebook的SDK到页面中: 在js中引进以下代码,初始化 // facebook window.fbAsyncIn ...