【JVM】性能调优

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Francis123580/article/details/82390932

问题 & 目标

JVM问题:CPU load过高、请求延迟、TPS降低、内存泄漏

调优目标:使用较小的内存占用获得较高的吞吐量 或者 较低的延迟

调优指标:

  • 内存占用:程序正常运行需要的内存大小
  • 延迟:由于垃圾收集而引起的程序停顿时间
  • 吞吐量:用户程序运行时间占用用户程序和垃圾收集占用总时间比值

参考日志

  1. 系统运行日志:程序代码打印的日志,描述了代码级别的系统运行轨迹
  2. 堆栈错误信息:根据堆栈信息可以初步定位问题所在
  3. GC日志:程序启动时用-XX:+PrintGCDetails-xloggc:/data/jvm/gc.log把程序运行时GC过程记录下来,通过GC日志分析每块内存区域的GC的频率、时间,从而发现问题所在
  4. 线程快照:通过jstack pid,可以dump出当前进程中线程的快照信息,通过观察线程在某一时刻的状态,如果系统中存在请求超时、死循环、死锁情况时,可以根据快照进一步确定问题。
  5. 堆转储快照:程序启动时使用-XX:+HeapDumpOnOutOfMemory-XX:HeapDumpPath=/data/jvm/dumpfile.hprof命令,当程序发生内存溢出时,把当时的内存快照以文件形式转储,事后对当时的内存使用情况分析

JVM调优工具

  1. jps命令:查看JVM启动的所有进程、执行主类的全名、JVM启动参数

  2. jstat命令:监视虚拟机信息,例jstat -gc pid 500 10(每500ms打印各个区容量、使用容量、gc时间,打印10次)

  3. jmap命令:查看堆内存信息,例jmap -histo pid(打印当前堆中每个类的实例数量和内存占用)

  4. jhat命令:通过浏览器分析对应的内存快照,例jhat -port 9810 -J-Xmx4G /data/jvm/dumpfile_jmap.hprof(以9810端口启动jhat内嵌的服务器)

  5. jconsole / jvisualvm:分析内存信息(各个区内存变化情况)

JVM调优经验

说明:

  • 一般情况采用默认配置,在测试中根据系统运行状况和GC日志、内存监控进行合理调整
  • 新生代越大,老年代越小,Full GC 频率越高,但 Full GC 时间短
  • 新生代越小,老年代越大,Full GC 频率越低,但 Full GC 时间长

参数设置:

  1. -Xms-Xmx的值设成相等,Heap不够用时,会发生内存抖动,影响程序运行稳定性
    堆大小默认为-Xms指定大小;
    默认空闲堆内存小于40%时,JVM会扩大堆到-Xmx指定的大小;
    空闲堆内存大于70%时,JVM会减小堆到Xms指定大小;
    如果在 Full GC 后满足不了内存需求会动态调整,这个阶段比较耗费资源

  2. 新生代尽量设置大一些,让对象在新生代多存活一段时间,每次 Minor GC 都要尽可能多的收集垃圾对象,防止或延迟对象进入老年代的机会,从而减少 Full GC 的频率

  3. 老年代如果使用CMS收集器,新生代可以不用太大(CMS并行收集速度很快,可以和用户线程并发执行)

  4. 方法区大小设置,1.6之前需要考虑系统运行时动态增加的常量、静态变量,1.7只要能装下类信息就可以

代码实现:

  1. 避免创建过大的对象及数组:过大对象在新生代没有足够空间会直接进入老年代,如果是短命大对象,会提前触发 Full GC
  2. 避免同时加载大量数据:可以分批读取,用完后尽快清空引用
  3. 用完尽快清空集合中对象的引用: 尽快回收,避免进入老年代
  4. 在合适场景采用软引用、弱引用:内存溢出前会把它们列入回收范围进行二次回收
  5. 避免产生死循环:死循环产生后,可能产生大量实例,导致空间占满

JVM参数

参数 说明 实例
-Xms 初始堆大小,默认物理内存的 1/64 -Xms512M
-Xmx 最大堆大小,默认物理内存的 1/4 -Xmx2G
-Xmn 新生代内存大小,官方推荐为整个堆的 3/8 -Xmn512M
-Xss 线程堆栈大小,jdk1.5及之后默认1M,之前默认 256k -Xss512k
-XX:NewRatio=n 设置新生代和年老代的比值。例:3,表示年轻代与年老代比值为1:3 -XX:NewRatio=3
-XX:SurvivorRatio=n 年轻代中Eden区与两个Survivor区的比值。例:8,表示Eden:Survivor=8:1:1 -XX:SurvivorRatio=8
-XX:PermSize=n 永久代初始值,默认为物理内存的 1/64 -XX:PermSize=128M
-XX:MaxPermSize=n 永久代最大值,默认为物理内存的 1/4 -XX:MaxPermSize=256M
-verbose:class 在控制台打印类加载信息
-verbose:gc 在控制台打印垃圾回收日志
-XX:+PrintGC 打印GC日志,内容简单
-XX:+PrintGCDetails 打印GC日志,内容详细
-XX:+PrintGCDateStamps 在GC日志中添加时间戳
-Xloggc:filename 指定gc日志路径 -Xloggc:/data/jvm/gc.log
-XX:+UseSerialGC 年轻代设置串行收集器Serial
-XX:+UseParallelGC 年轻代设置并行收集器Parallel Scavenge
-XX:ParallelGCThreads=n 设置Parallel Scavenge收集时使用的CPU数。并行收集线程数 -XX:ParallelGCThreads=4
-XX:MaxGCPauseMillis=n 设置Parallel Scavenge回收的最大时间(毫秒) -XX:MaxGCPauseMillis=100
-XX:GCTimeRatio=n 设置Parallel Scavenge垃圾回收时间占程序运行时间的百分比。公式为1/(1+n) -XX:GCTimeRatio=19
-XX:+UseParallelOldGC 设置老年代为并行收集器ParallelOld收集器
-XX:+UseConcMarkSweepGC 设置老年代并发收集器CMS
-XX:+CMSIncrementalMode 设置CMS收集器为增量模式,适用于单CPU情况

参考:
https://blog.csdn.net/huyuyang6688/article/details/81490570

猜你喜欢

转载自blog.csdn.net/Francis123580/article/details/82390932