JVM性能调优概述与实战

JVM性能调优实战

1、调优的原则

  • 多数的Java应用不需要在服务器上进行GC优化,虚拟机内部已有很多优化来保证应用的稳定运行,所以不要为了调优而调优,不当的调优可能适得其反
  • 在应用上线之前,先考虑将机器的MM参数设置到最优(适合)
  • 在进行GC优化之前,需要确认项目的架构和代码等已经没有优化空间。我们不能指望一个系统架构有缺陷或者代码层次优化没有穷尽的应用,通过GC优化令其性能达到一个质的飞跃
  • G.C优化是一个系统而复杂的工作,没有万能的调优策略可以满足所有的性能指标。GC优化必须建立在我们深入理解各种垃圾回收器的基础上,才能有事半功倍的效果
  • 处理吞吐量和延迟问题时,垃圾处理器能使用的内存越大,即java堆空间越大垃圾收集效果越好,应用运行也越流畅。这称之为GC内存最大化原则
  • 在这三个属性(吞吐量、延迟、内存)中选择其中两个进行jvm调优,称之为GC调优3选2

2、什么情况下需要调优

  •  Heap内存(老年代)持续上涨达到设置的最大内存值o Full GC次数频繁
  • GC停顿(Stop World)时间过长(超过1秒,具体值按应用场景而定)·应用出现OutOfMemory等内存异常
  • 应用出现OutOfDirectMemoryError等内存异常( failed to allocate 16777216 byte(s) of direct memory(used: 1056964615, max: 1073741824))
  • 应用中有使用本地缓存且占用大量内存空间·系统吞吐量与响应性能不高或下降
  • 应用的CPU占用过高不下或内存占用过高不下

3、调优钱需要知道一些概念

  1. 吞吐量:用户代码时间/(用户代码执行时间+垃圾回收时间)。是评价垃圾收集器能力的重要指标之一,是不考虑垃圾收集引起的停顿时间或内存消耗,垃圾收集器能支撑应用程序达到的最高性能指标。吞吐量越高算法越好。
  2. 低延迟:SIW越短,响应时间越好。评价垃圾收集器能力的重要指标,度量标准是缩短由于垃圾收集引起的停顿时间或完全消除因垃圾收集所引起的停顿,避免应用程序运行时发生抖动。暂停时间越短算法越好
  3. 在设计(或使用)GC算法时,我们必须确定我们的目标:一个GC算法只可能针对两个目标之一(即只专注于最大吞吐量或最小暂停时间),或尝试找到一个二者的折衷
  4. MinorGC尽可能多的收集垃圾对象。我们把这个称作MinorGC原则,遵守这一原则可以降低应用程序FullGC
  5. 堆大小调整的着手点、分析点:
    • 统计Minor GC持续时间
    • 统计Minor GC的次数
    • 统计Full GC的最长持续时间
    • 统计最差情况下Full GC频率
    • 统计GC持续时间和频率对优化堆的大小是主要着手点
    • 我们按照业务系统对延迟和吞吐量的需求,在按照这些分析我们可以进行各个区大小的调整
  6. 一般来说吞吐量优先的垃圾回收器: -XX:+UseParallelGC -xX:+UseParallelOldGC,即常规的(PS/PO)
  7. 响应时间优先的垃圾回收器:CMS、G1

4、JVM常用参数解读

  1. Xms是指设定程序启动时占用内存大小。一般来讲,大点,程序会启动的快一点,但是也可能会导致机器暂时间变慢
  2. Xmx是指设定程序运行期间最大可占用的内存大小。如果程序运行需要占用更多的内存,超出了这个设置值,就会抛出OutOfMemory异常
  3. Xss是指设定每个线程的堆栈大小。这个就要依据你的程序,看一个线程大约需要占用多少内存,可能会有多少线程同时运行等
  4. Xmn、-XX:NewSize/-XX:MaxNewSize.-XX:NewRatio
    • 高优先级:-XX:NewSize/-XX:MaxNewSize
    • 中优先级: -Xmn(默认等效-Xmn=-XX:NewSize=-XX:MaxNewSize=?)
    • 低优先级:-XX:NewRatio

5.如果想在日志中追踪类加载与类卸载的情况,可以使用启动参数-XX:TraceClassLoading-XX:TraceClassUnloading

5、常用的性能调优工具

  1.MAT  2.jvisualvm  3.jconsole  4.Arthas  5.show-busy-java-threads(开源工具)

6、线上排查问题的一般流程  

  1.CPU占用过高排查流程

    • 利用top命令可以查出占CPU最高的的进程pid,如果pid为9876⒉
    • 然后查看该进程下占用最高的线程id 【top -Hp 9876】
    • 假设占用率最高的线程ID为6900,将其转换为16进制形式(因为java native线程以16进制形式输出)【printf '%x\n' 6900)
    • 利用jstack:打印出 java 线程调用栈信息【jistack 9876 | grep 'Ox1af4'-A 50 --color】,这样就可以更好定位问题

2.内存占用过高排查流程

    • 查找进程id: 【top -d 2 -c】
    • 查看JMM堆内存分配情况: jmap -heap pid
    • 查看占用内存比较多的对象jmap -histo pid | head -n 100
    • 查看占用内存比较多的存活对象jimap -histo:live pid | head -n 100

 

 

 



posted @ 2022-01-15 15:31  TristeLymo  阅读(218)  评论(0)    收藏  举报