• 记录一次Metaspace扩容引发FGC的调优总结


    开始之前

      在开始之前先记录一个我碰到的jvm调优的坑。那就是…

    为啥我配置到idea64exe.vmoptions中的参数没有生效???

      由于之前一直是在mac上开发,本地开发时当需要优化jvm参数的时候直接去idea的安装目录里修改idea.vmoptions就可以了,换到windows以后想当然的也这么改,但是发现似乎我配置的参数并没有生效, what‘s the f***?探索了一番终于发现了问题所在。

      windows是基于用户登录的,idea会为每个用户在当前用户根目录下创建一份配置信息,所以在idea安装目录下修改idea.vmoptions是不生效的,如图:

      不知道管理员用户登录的话是不是就可以直接修改idea安装目录的ideaexe.vmoptions了,有一个很简单的方法判断你当前的idea项目使用的是哪里的配置信息。

    发现问题

      ok,现在终于可以优化我们的jvm参数了,下面是一套我经常用的参数,在我以前开发的时候基本都是用这套参数,我也就直接复制到了idea64exe.vmoptions。

    -Xms1024m
    -Xmx1024m
    -Xmn512m
    -XX:MetaspaceSize=256m
    -XX:MaxMetaspaceSize=256m
    -XX:ReservedCodeCacheSize=512m
    -XX:+UseConcMarkSweepGC
    -XX:SoftRefLRUPolicyMSPerMB=50
    -ea
    -Dsun.io.useCanonCaches=false
    -Djava.net.preferIPv4Stack=true
    -XX:+HeapDumpOnOutOfMemoryError
    -XX:-OmitStackTraceInFastThrow

      保存重启idea以后,开一个项目,嗯,没啥感觉,一切正常。开两个项目,嗯,怎么有点卡呢。又开了一个项目,噩梦开始了,idea开始爆卡,点一下卡2s的那种。

    定位原因

    1. jps:查看idea platform的进程ID

    2. jstat -gcutil pid 3s:查看进程垃圾回收情况

     

      从上图可以看出,刚开始YGC和FGC都很健康,但随着我打开的项目越来越多,FGC开始飙升,直接导致了页面明显的卡顿,我试着关掉了几个项目,只保留一个,FGC慢慢变小,分析上图可以看出,M的占比随着FGC略有下降,从93.7%下降到93.2%左右,推测可能是Metaspace扩容导致的FGC。

    确认原因

      通过jstat -gc pid 3s:可以查看metaspace具体使用情况,下图可以看出metaspace发生了扩容。

      更简单的是,通过命令jvisualvm,打开Java VisualVM查看mataspace具体使用大小。

      果然,当我同时打开多个项目时,metaspace发生了扩容,并且最终mataspace的使用量达到了接近250M,几乎达到了上面我配置的参数-XX:MetaspaceSize=256m,于是我将上面配置中关于mataspace的参数删掉。

    -Xms1024m
    -Xmx1024m
    -Xmn512m
    -XX:ReservedCodeCacheSize=512m
    -XX:+UseConcMarkSweepGC
    -XX:SoftRefLRUPolicyMSPerMB=50
    -ea
    -Dsun.io.useCanonCaches=false
    -Djava.net.preferIPv4Stack=true
    -XX:+HeapDumpOnOutOfMemoryError
    -XX:-OmitStackTraceInFastThrow

       再次jstat -gcutil pid 3s查看GC情况。

      这次FGC情况大有改善,随着我开的项目越来越多,FGC也只是从6次涨到了8次。至此,问题基本就解决了,但如果只是这样的话,我写这篇笔记的意义就不大了,接下来的才是重点。

    深入探究

      我尝试重新添加了mataspace的参数,如下:

    -Xms1024m
    -Xmx1024m
    -Xmn512m
    -XX:MetaspaceSize=384m
    -XX:MaxMetaspaceSize=384m
    -XX:ReservedCodeCacheSize=512m
    -XX:+UseConcMarkSweepGC
    -XX:SoftRefLRUPolicyMSPerMB=50
    -ea
    -Dsun.io.useCanonCaches=false
    -Djava.net.preferIPv4Stack=true
    -XX:+HeapDumpOnOutOfMemoryError
    -XX:-OmitStackTraceInFastThrow

      再次jstat -gcutil pid 3s查看GC情况:

      上图是我同时开了5个项目的GC情况,FGC只有1次,这才是让我觉得困惑的地方,也就是说当我设置了MetaspaceSize=384m和不设置的时候,是有区别的,在网上看了很多关于mataspace的文章,我发现自己一直以来都没有搞懂-XX:MetaspaceSize=256M的真正含义,这个配置的含义并不是初始化元数据区大小为256m,而仅仅表示的是触发FGC的阈值,至于配置和不配置的区别,也就很明显了,这个知识点在书上看到过但是没放在心上,在实际碰到问题的时候才恍然大悟。

      Metaspace由于使用不断扩容到-XX:MetaspaceSize参数指定的量,就会发生FGC;且之后每次Metaspace扩容都可能会发生FGC。

      我们知道Metapsace是在jdk8中引入的,之前叫permGen,就是我们所说的永久代。在jdk8以前,我们配置-XX:PermSize=256m,那就是说初始化一块256m的内存作为永久代。但是mataspace就不一样了,很明显,mataspace要比perm高级的多。

    总结

    • 如果没有配置-XX:MetaspaceSize,那么触发FGC的阈值是21807104(约20.8m)。

    • 如果配置了-XX:MetaspaceSize,那么触发FGC的阈值就是配置的值。

    • 配置比不配置好,实际开发时,可以先开几个项目查看一下metaspace大概占用多少内存,这个跟项目大小和复杂度有关,再根据实际情况配置-XX:MetaspaceSize。

    查看当前java进程,一般用来查找进程ID(PID)

    • jps:查看当前java进程及PID
    • jps -l:输出主类或者jar的完全路径名
    • jps -v:输出jvm参数

    动态查看gc情况

    • jstat -gc pid 3s: 每隔3s打印当前pid进程的堆内存详细信息
    • jstat -gcutil pid 3s: 每隔3s打印当前pid进程的堆内存总体GC统计信息

    可视化工具jvisualvm

      命令行直接输入jvisualvm可打开可视化工具,动态查看java进程内部详细信息

    结合以上3种途径,可以查看java进程的详细使用情况和GC情况。

  • 相关阅读:
    关于委托的一篇不错的文章(C# 中的委托和事件)
    李建忠老师的《.net框架程序设计(修订版)》电子书下载地址,超级推荐
    普通无线路由变成纯AP模式
    CLR到底是什么?是怎么工作的?
    HTTP协议的三个问题
    桌面战争——揭秘中国互联网的里程碑之战
    B2C这点事儿
    不用baidu,不用google,你有bing啊
    让.net程序脱离.NET Framework在Linux下运行
    哥乃一介光棍
  • 原文地址:https://www.cnblogs.com/fingerboy/p/11690772.html
Copyright © 2020-2023  润新知