• 【JVM】JVM优化过程全记录


    请大神移步:https://segmentfault.com/a/1190000010510968?utm_source=tuicool&utm_medium=referral

    今天看JVM群里有人发了一个GC情况,让人帮忙看优化的,于是我也凑热闹发了出来想让群里的大神们指导优化一下,以下是优化过程记录.

    一开始我贴了下面的两张图

    jstat看GC记录
    jstat -gcutil pid 1000 20

    clipboard.png

    jcmd看VM参数(第一次使用这个命令)
    jcmd pid VM.flags

    clipboard.png

    可以看到YGC了8W多次,FGC有1100+,相比较另一个发出来求教的,我这个更糟糕,他的是运行了3天左右 FGC370次

    然后飞神让我看下运行时间
    ps -p pid -o etime

    clipboard.png

    我的也是跑了3天左右,感觉优化空间非常的大

    又让我拉了JVM配置
    jinfo -flags pid(没权限,没执行成功)
    ps aux | grep pid

    clipboard.png

    发现我的JVM完全没做过优化,据我自己的印象,就改过PermSize,因为这个OOM过,所以调大了一点。

    然后飞神给了我一份他之前用过的配置
    JAVA_OPTS="-Xms2g -Xmx2g -Xmn512m -XX:MaxPermSize=256m  -server -Xss256k -XX:PermSize=128M -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:/data/log/gclog/gc.log -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/data/log/jvmdump/jvm.bin -XX:+UseConcMarkSweepGC -XX:+UseParNewGC  -XX:CMSInitiatingOccupancyFraction=75 -XX:+UseCMSInitiatingOccupancyOnly -XX:+UseCMSCompactAtFullCollection -XX:CMSFullGCsBeforeCompaction=0 -XX:+CMSClassUnloadingEnabled -XX:+TieredCompilation  -XX:+PrintTenuringDistribution -XX:+PrintGCApplicationStoppedTime -XX:+PrintHeapAtGC

    并嘱咐了一句loggc和dumpPath提前mkdir

    因为已经是周五晚上了,我没有权限直接修改这个配置,所以准备下周一再配上去看效果。

    万万没想到,回家路上,笨神出来说话了,要我看下存活实例

    jmap -histo:live pid

    clipboard.png

    由于没有开启GC日志,于是笨神让我开着jstat(飞神提到jstat -gccause pid可以跟踪gc情况),然后在另一个窗口执行jmap -histo:live

    刚开始没明白,后来才知道原来这个命令可以触发Full GC
    

    clipboard.png

    可以看到执行了Full GC以后Old区从90%降到了79%,FGC效果很差,说明活对象太多了。

    回过头去看jmap实例,发现AtomicInteger这个类对象特别的多,竟然有300多万个实例,已经是top2了。

    翻看代码没有发现有使用这个类的地方,初步怀疑是依赖的jar包使用的,笨神建议dump用MAT分析一下。

    dump命令导出文件
    jmap -dump:format=b,file=pid.dump pid

    检查了一下项目代码后,发现了问题,项目代码就不贴了
    

    项目中有一个统计API调用次数的类使用了AtomicInteger,在这个类里针对每个用户都会生成大概六七十个AtomicInteger实例,每次上报过数据之后只是简单的把值设置为0,导致负责统计的实例一直持有这些AtomicInteger,而且随着新用户的不断增加,这些实例数量还会持续增长,最终会导致内存溢出。

    修改完这个BUG,重新上线后,跑了一段时间查看gc情况

    clipboard.png

    clipboard.png

    可以看到比之前好一些了 但是FGC的次数还是比较多,照这情况下去一天的FGC估计会有200+,这当然是不可接受的(前面说的另一个人370次FGC,飞神说如果是跑了半年的话还可以接受)。

    看了飞神推荐的阿里毕玄大师的文章为什么不建议

    于是准备先不上CMS GC,就简单的把Xms,Xmn和GC日志配置了一下

    -Xms2048m -Xmx2048m -XX:PermSize=128m -XX:MaxPermSize=128m -Xss256k -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:/data/project/delivery_v9/code/logs/gc.log -XX:GCLogFileSize=50m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/data/project/delivery_v9/tomcat/jvmdump/jvm.dump

    运行了一天左右看下对比结果

    未配置

    clipboard.png

    clipboard.png

    已配置

    clipboard.png

    clipboard.png

    可以看到配置完以后对GC影响还是挺大的(不管是YGC还是FGC),当然这也是必然的,毕竟没有配置的机器初始内存比较小,在不断扩容的过程中会频繁的GC,而且这个时候其实没配置的那台机器内存还没有扩充到上限,在资源充足的情况下,这种动态扩容显然是完全没有必要的。

    配置完的机器虽然GC时间和次数已经降了很多了,但是还是没达到期望的结果,考虑到这个程序短时间的活对象是比较多的,可以通过调整年轻代和老年代的内存占比来减少因为年轻代内存不足导致晋升到老年代的对象。

  • 相关阅读:
    IT项目中使用 json格式数据 保存项目配置信息, 在配置文件再读取json文件的内容进行赋值
    python 使用eval() 可以将json格式的数据,转换为原始数据
    python 取出字典的键或者值/如何删除一个字典的键值对/如何遍历字典
    python2 中 unicode 和 str 之间的转换及与python3 str 的区别
    python 将列表嵌套字典的unicode字符串转换为str格式的字符串的方法
    Django 项目拆分配置文件settings.py
    苹果笔记本调整 pycharm 字体大小的地方
    django rest framework 向数据库中插入数据时处理外键的方法
    java实现文件的压缩和解压
    java 跨数据库导入大数据
  • 原文地址:https://www.cnblogs.com/itworkers/p/11791778.html
Copyright © 2020-2023  润新知