JVM 性能调优 及 为什么要减少 Full GC

本文涉及的产品
性能测试 PTS,5000VUM额度
日志服务 SLS,月写入数据量 50GB 1个月
简介: JVM 性能调优 及 为什么要减少 Full GC

本文为博主原创,未经允许不得转载:

  系统上线压测,需要了解系统的瓶颈以及吞吐量,并根据压测数据进行对应的优化。

  对压测进行 JVM 性能优化,有两条思路:

  第一种情况 : 使用压测工具 jmeter 进行小量并发业务测试, 通过 top 命令查看cpu是否会急速飙升。若在 小并发量压测时或单独调试时,出现 cpu 性能飙升,

    那就需要对对应的业务接口进行代码分析,分析消耗cpu 的原因。

  第二种情况:使用压测工具jmeter ,jvisulam 等进行大并发量业务测试,并使用 top 命令实时监控 cpu ,以及内存的使用情况,查看 垃圾回收

    MinorGC 和 Full GC 的频率和情况。根据 GC 的数据进行对应的JVM参数设置,提高系统的可用性。

如何进行第一种情况调优:

  1. CPU 迅速飙升,在业务服务器上进行监控,

    1.通过 top 命令定位到占用 CPU 和内存 最高的线程

    2. 并将对应的线程转为16进制,通过jstack 查询该线程的堆栈信息,从而定位到对应的代码,并进行代码分析

    3. 进行代码性能优化

第二种情况调优:

  第二种情况调优属于 JVM 参数性能调优,主要通过设置 堆(新生代和老年代)的大小以及GC 垃圾回收器,从而提高服务的性能。

    该调优需要在压测时,需要对该 java 进程实时的垃圾回收情况进行监控。分析在压测业务吞吐量相对稳定时,GC的回收情况。  

    1. 使用 jstat 命令对指定的java 进程进行实时监控。并计算出一些关键数据。并给自己的系统设置一些初始性的JVM 参数:

      比如 堆内存大小,年轻代大小,Eden和Survivor的比例,老年代的大小,大对象的阈值,大龄对象进入老年代的阈值等。

    2. 查看年轻代对象的增长速率:

      可以执行命令 jstat -gc pid 1000 10 (每隔1秒执行1次命令,共执行10次),通过观察EU(eden区的使用)来估算每秒eden大概新增多少对象,

    如果系统负载不高,可以把频率1秒换成1分钟,甚至10分钟来观察整体情况。注意,一般系统可能有高峰期和日常期,所以需要在不

    同的时间分别估算不同情况下对象增长速率。

    3. Young GC的触发频率和每次耗时

      知道年轻代对象增长速率我们就能推根据eden区的大小推算出Young GC大概多久触发一次,Young GC的平均耗时可以通过 YGCT/YGC公式算出,

    根据结果我们大概就能知道系统大概多久会因为Young GC的执行而卡顿多久。

 

    4. 每次Young GC后有多少对象存活和进入老年代

      这个因为之前已经大概知道Young GC的频率,假设是每5分钟一次,那么可以执行命令 jstat -gc pid 300000 10 ,观察每次结果eden,survivor和老年代

    使用的变化情况,在每次gc后eden区使用一般会大幅减少,survivor和老年代都有可能增长,这些增长的对象就是每次Young GC后存活的对象,同时还可以看

    出每次Young GC后进去老年代大概多少对象,从而可以推算出老年代对象增长速率。

    5. Full GC的触发频率和每次耗时

      知道了老年代对象的增长速率就可以推算出Full GC的触发频率了,Full GC的每次耗时可以用公式 FGCT/FGC 计算得出。

    6. 优化思路其实简单来说就是尽量让每次Young GC后的存活对象小于Survivor区域的50%,都留存在年轻代里。

      尽量别让对象进入老年代。尽量减少Full GC的频率,避免频繁Full GC对JVM性能的影响。

    在调试JVM 的堆大小时,可以根据JVM 堆得内存模型图进行推算参数值:

    

 

  为什么要减少 Full GC:

    通过设置JVM 的参数,减少Full GC 触发的频率,因为 Full GC 会导致 STW :top一the一World,简称STW,指的是Gc事件发生过程中,

  会产生应用程序的停顿。停顿产生时整个应用程序线程都会被暂停,没有任何响应,有点像卡死的感觉,这个停顿称为STW。

    为什么要减少 Full GC ,因为 Young GC 每次扫描的对象少,且对象的生命周期较短,容器GC ,而 Full GC 不仅需要扫描清理老年代的

  垃圾对象,还需要清理 metaspace和新生代的垃圾对象,由于老年代中所保存的对象是生命周期较长的对象,不易清理,比较耗时,这就会

  导致 STW 时间变长,服务不可用或卡顿的现象也就越长。 


  常用的 JVM 参数配置:

    

参数 说明 实例
-Xms 初始堆大小,默认物理内存的1/64 -Xms512M
-Xmx 最大堆大小,默认物理内存的1/4 -Xms2G
-Xmn 新生代内存大小,官方推荐为整个堆的3/8 -Xmn512M
-Xss 线程堆栈大小,jdk1.5及之后默认1M,之前默认256k -Xss512k
-XX:NewRatio=n 设置新生代和年老代的比值。如:为3,表示年轻代与年老代比值为1:3,年轻代占整个年轻代年老代和的1/4 -XX:NewRatio=3
-XX:SurvivorRatio=n 年轻代中Eden区与两个Survivor区的比值。注意Survivor区有两个。如:8,表示Eden:Survivor=8:1:1,一个Survivor区占整个年轻代的1/8 -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情况。  


 

标签: JVM

相关实践学习
通过性能测试PTS对云服务器ECS进行规格选择与性能压测
本文为您介绍如何利用性能测试PTS对云服务器ECS进行规格选择与性能压测。
目录
相关文章
|
2月前
|
Arthas 监控 Java
(十一)JVM成神路之性能调优篇:GC调优、Arthas工具详解及各场景下线上最佳配置推荐
“在当前的互联网开发模式下,系统访问量日涨、并发暴增、线上瓶颈等各种性能问题纷涌而至,性能优化成为了现时代开发过程中炙手可热的名词,无论是在开发、面试过程中,性能优化都是一个常谈常新的话题”。
170 3
|
2月前
|
运维 Java Linux
(九)JVM成神路之性能调优、GC调试、各内存区、Linux参数大全及实用小技巧
本章节主要用于补齐之前GC篇章以及JVM运行时数据区的一些JVM参数,更多的作用也可以看作是JVM的参数列表大全。对于开发者而言,能够控制JVM的部分也就只有启动参数了,同时,对于JVM的性能调优而言,JVM的参数也是基础。
|
1月前
|
算法 Java 应用服务中间件
探索JVM垃圾回收算法:选择适合你应用的最佳GC策略
探索JVM垃圾回收算法:选择适合你应用的最佳GC策略
|
1月前
|
存储 监控 算法
深入解析JVM内部结构及GC机制的实战应用
深入解析JVM内部结构及GC机制的实战应用
|
1月前
|
监控 算法 Java
深入理解Java虚拟机:JVM调优与性能提升
本文旨在为Java开发者提供一条清晰的路径,以深入掌握Java虚拟机(JVM)的内部机制和性能调优技巧。通过具体案例分析,我们将探讨如何识别性能瓶颈、选择合适的工具进行监控与调试,以及实施有效的优化策略,最终达到提高应用程序性能的目的。文章不仅关注理论,更注重实践应用,帮助读者在面对复杂的Java应用时能够游刃有余。
49 0
|
1月前
|
Arthas Prometheus 监控
使用JDK自带工具调优JVM的常用命令
使用JDK自带工具调优JVM的常用命令
|
1月前
|
Java Docker 索引
记录一次索引未建立、继而引发一系列的问题、包含索引创建失败、虚拟机中JVM虚拟机内存满的情况
这篇文章记录了作者在分布式微服务项目中遇到的一系列问题,起因是商品服务检索接口测试失败,原因是Elasticsearch索引未找到。文章详细描述了解决过程中遇到的几个关键问题:分词器的安装、Elasticsearch内存溢出的处理,以及最终成功创建`gulimall_product`索引的步骤。作者还分享了使用Postman测试接口的经历,并强调了问题解决过程中遇到的挑战和所花费的时间。
|
1月前
|
存储 算法 Oracle
不好意思!耽误你的十分钟,JVM内存布局还给你
先赞后看,南哥助你Java进阶一大半在2006年加州旧金山的JavaOne大会上,一个由顶级Java开发者组成的周年性研讨会,公司突然宣布将开放Java的源代码。于是,下一年顶级项目OpenJDK诞生。Java生态发展被打开了新的大门,Java 7的G1垃圾回收器、Java 8的Lambda表达式和流API…大家好,我是南哥。一个Java学习与进阶的领路人,相信对你通关面试、拿下Offer进入心心念念的公司有所帮助。
不好意思!耽误你的十分钟,JVM内存布局还给你
|
1月前
|
存储 算法 Java
JVM自动内存管理之垃圾收集算法
文章概述了JVM内存管理和垃圾收集的基本概念,提供一个关于JVM内存管理和垃圾收集的基础理解框架。
JVM自动内存管理之垃圾收集算法
|
1月前
|
存储 Java 程序员
JVM自动内存管理之运行时内存区
这篇文章详细解释了JVM运行时数据区的各个组成部分及其作用,有助于理解Java程序运行时的内存布局和管理机制。
JVM自动内存管理之运行时内存区