【JVM】性能调优

图片

一、前言

性能调优,顾名思义,就是对系统或软件的性能进行优化,以提高其运行效率和响应速度。在计算机科学中,性能调优通常涉及到硬件、操作系统、数据库、网络等多个方面。对于Java开发者来说,JVM(Java虚拟机)的性能调优是非常重要的一环,因为JVM的性能直接影响到Java程序的运行效率。

性能调优包含多个层次,比如:架构调优、代码调优、JVM调优、数据库调优、操作系统调优等。架构调优和代码调优是JVM调优的基础,其中架构调优是对系统影响最大的。

图片

性能调优基本上按照以下步骤进行:明确优化目标、发现性能瓶颈、性能调优、通过监控及数据统计工具获得数据、确认是否达到目标。

二、性能定义

要查找和评估器性能瓶颈,首先要知道性能定义,对于jvm调优来说,我们需要知道以下三个定义属性,依作为评估基础:

吞吐量:重要指标之一,是指不考虑垃圾收集引起的停顿时间或内存消耗,垃圾收集器能支撑应用达到的最高性能指标。

延迟:其度量标准是缩短由于垃圾啊收集引起的停顿时间或者完全消除因垃圾收集所引起的停顿,避免应用运行时发生抖动。

内存占用:垃圾收集器流畅运行所需要 的内存数量。

这三个属性中,其中一个任何一个属性性能的提高,几乎都是以另外一个或者两个属性性能的损失作代价,不可兼得,具体某一个属性或者两个属性的性能对应用来说比较重要,要基于应用的业务需求来确定。

三、JVM调优的时机

遇到以下情况,就需要考虑进行JVM性能调优:

  1. 程序运行缓慢,响应时间过长;

  2. 程序运行时占用大量内存;

  3. 程序在高并发环境下运行不稳定;

  4. Heap内存(老年代)持续上涨达到设置的最大内存值;

  5. Full GC 次数频繁;

  6. GC 停顿时间过长(超过1秒);

  7. 应用出现OutOfMemory 等内存异常;

  8. 应用中有使用本地缓存且占用大量内存空间;

  9. 系统吞吐量与响应性能不高或下降。

四、调优的基本原则

优先架构调优和代码调优,JVM优化是不得已的手段,大多数的Java应用不需要进行JVM优化。

在调优前,我们需要理解相应原理和掌握技能:

  • 理解JVM的工作原理和架构;

  • 掌握JVM的性能指标和监控工具;

  • 根据实际需求和场景选择合适的JVM参数;

  • 通过实验和数据分析来验证调优效果。

在调优过程中,应该谨记以下3个原则,以便完成垃圾收集的调优,从而达到应用程序的性能要求。

  1. MinorGC回收原则:每次minor GC 都要尽可能多的收集垃圾对象。以减少应用程序发生Full GC的频率。

  2. GC内存最大化原则:处理吞吐量和延迟问题时候,垃圾处理器能使用的内存越大,垃圾收集的效果越好,应用程序也会越来越流畅。

  3. GC调优3选2原则: 在性能属性里面,吞吐量、延迟、内存占用,我们只能选择其中两个进行调优,不可三者兼得。

五、JVM调优目标

JVM调优的主要目标是提高程序的运行效率和响应速度,减少资源消耗,提高系统的稳定性和可扩展性。具体来说,主要包括以下几个方面:

  1. 提高程序的运行速度;

  2. 减少内存消耗;

  3. 减少GC的频率和时间;

  4. 提高系统的吞吐量和并发能力。

吞吐量、延迟、内存占用三者类似CAP,构成了一个不可能三角,只能选择其中两个进行调优,不可三者兼得。

  • 延迟:GC低停顿和GC低频率;

  • 低内存占用;

  • 高吞吐量;

选择了其中两个,必然会会以牺牲另一个为代价。

六、调优工具

常用的JVM调优工具有:

  • JConsole:Java自带的图形化监控工具,可以实时查看JVM的各种性能指标;

  • VisualVM:功能强大的多合一性能分析工具,可以监控多个Java进程,提供详细的性能分析报告;

  • JProfiler:专业的Java性能分析工具,可以深入分析Java代码的执行效率,找出性能瓶颈;

  • Java Mission Control:Oracle推出的新一代Java性能分析工具,可以实时监控和分析Java应用的性能。

  • GCViewer:垃圾回收日志文件分析工具,可以非常直观地分析出待调优点。Memory,分析Totalheap、Tenuredheap、Youngheap内存占用率及其他指标,理论上内存占用率越小越好;Pause,分析Gc pause、Fullgc pause、Total pause三个大项中各指标,理论上GC次数越少越好,GC时长越小越好;

图片

七、JVM调优步骤

JVM调优的基本步骤如下:

  • 分析和定位问题:通过性能监控工具收集数据,分析GC日志及dump文件,分析程序的运行状况,找出性能瓶颈;

  • 选择合适的JVM参数:根据实际需求和场景,确定JVM调优量化目标,调整JVM的内存分配、垃圾回收策略等参数,依次调优内存、延迟、吞吐量等指标;

  • 进行实验和测试:修改JVM参数后,重新运行程序,观察性能变化,验证调优效果;

  • 分析和总结:对比观察调优前后的差异,不断的分析和调整,直到找到合适的JVM参数配置;

以上操作步骤中,某些步骤是需要多次不断迭代完成的。一般是从满足程序的内存使用需求开始的,之后是时间延迟的要求,最后才是吞吐量的要求,要基于这个步骤来不断优化,每一个步骤都是进行下一步的基础,不可逆行。

图片

八、JVM参数

JVM调优涉及的参数非常多,以下是一些常用的参数:

  1. -Xms:设置堆初始大小;

  2. -Xmx:设置堆最大大小;

  3. -Xmn:设置新生代大小;

  4. -XX:NewRatio:设置新生代与老年代的比例;

  5. -XX:SurvivorRatio:设置Eden区与Survivor区的比例;

  6. -XX:+UseParallelGC:选择并行垃圾回收器;

  7. -XX:+UseConcMarkSweepGC:选择CMS垃圾回收器;

  8. -XX:+UseG1GC:选择G1垃圾回收器;

  9. -XX:MaxGCPauseMillis:设置最大暂停时间目标;

  10. -XX:InitiatingHeapOccupancyPercent:设置触发Full GC的老年代占用率阈值。

图片

运行时JIT编译器优化参数

JIT编译指的是字节码编译为本地代码(汇编)执行,只有热点代码才会编译为本地代码。解释器执行节约内存,反之可以使用编译执行来提升效率。

图片

实用代码示例

示例1:设置和监控堆内存大小

JVM启动参数:

java -Xms512m -Xmx2g -jar YourApp.jar
  • -Xms512m:设置初始堆内存为512MB。

  • -Xmx2g:设置最大堆内存为2GB。


public class HeapSizeMonitoring {
    public static void main(String[] args) {
        // 获取运行时环境
        Runtime runtime = Runtime.getRuntime();

        // 打印JVM的初始内存和最大内存配置
        System.out.println("JVM初始内存大小:" + runtime.totalMemory() / (1024 * 1024) + " MB");
        System.out.println("JVM最大内存大小:" + runtime.maxMemory() / (1024 * 1024) + " MB");
    }
}

示例2:使用G1垃圾收集器并监控GC

JVM启动参数:

java -XX:+UseG1GC -XX:MaxGCPauseMillis=300 -XX:+PrintGCDetails -XX:+PrintGCDateStamps -jar YourApp.jar
  • -XX:+UseG1GC:使用G1垃圾收集器。

  • -XX:MaxGCPauseMillis=200:设置期望的最大GC暂停时间为300毫秒。

  • -XX:+PrintGCDetails 和 -XX:+PrintGCDateStamps:打印GC的详细信息和时间戳。

示例3:线程堆栈大小的设置与监控

JVM启动参数:

java -Xss512k -jar YourApp.jar
  • -Xss512k:设置每个线程的堆栈大小为512KB。

示例4:使用G1垃圾收集器并调优

JVM启动参数:

java -XX:+UseG1GC -XX:MaxGCPauseMillis=300 -XX:InitiatingHeapOccupancyPercent=50 -XX:+PrintGCDetails -XX:+PrintGCDateStamps -jar YourApp.jar
  • -XX:+UseG1GC:使用G1垃圾收集器。

  • -XX:MaxGCPauseMillis=300:尝试将GC的最大暂停时间控制在300毫秒以内。

  • -XX:InitiatingHeapOccupancyPercent=50:当堆占用率达到50%时开始GC。

  • -XX:+PrintGCDetails 和 -XX:+PrintGCDateStamps:打印详细的GC信息和时间戳。

示例5:监控垃圾收集信息

JVM启动参数:

java -XX:+PrintGC -XX:+PrintGCDetails -XX:+PrintGCDateStamps -jar YourApp.jar
  • -XX:+PrintGC:打印基本的GC信息。

  • -XX:+PrintGCDetails:打印GC的详细信息。

  • -XX:+PrintGCDateStamps:在GC日志中加入时间戳。

示例6:设置线程堆栈大小

JVM启动参数:

java -Xss1024k -jar YourApp.jar
  • -Xss1024k:设置每个线程的堆栈大小为1024KB。

示例7:监控类的加载和卸载

JVM启动参数:

java -XX:+TraceClassLoading -XX:+TraceClassUnloading -jar YourApp.jar
  • -XX:+TraceClassLoading:启用类加载跟踪。

  • -XX:+TraceClassUnloading:启用类卸载跟踪。

示例8:监控垃圾回收行为

JVM启动参数:

java -XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:gc.log -jar YourApp.jar
  • -XX:+PrintGCDetails:打印垃圾回收的详细信息。

  • -XX:+PrintGCDateStamps:在垃圾回收日志中加入时间戳。

  • -Xloggc:gc.log:将垃圾回收日志记录到指定文件。

示例9:配置和使用字符串去重功能

JVM启动参数:

java -XX:+UseStringDeduplication -XX:+PrintStringDeduplicationStatistics -jar YourApp.jar
  • -XX:+UseStringDeduplication:开启JVM的字符串去重功能。

  • -XX:+PrintStringDeduplicationStatistics:打印字符串去重的统计信息。

示例10:使用并行垃圾收集器

JVM启动参数:

java -XX:+UseParallelGC -XX:GCTimeRatio=4 -XX:+PrintGCDetails -jar YourApp.jar
  • -XX:+UseParallelGC:使用并行垃圾收集器。

  • -XX:GCTimeRatio=4:设置吞吐量目标,表示99%的时间用于应用程序,1%的时间用于垃圾收集。

  • -XX:+PrintGCDetails:打印垃圾收集的详细信息。

示例11:设置和监控ZGC垃圾收集器

JVM启动参数:

java -XX:+UnlockExperimentalVMOptions -XX:+UseZGC -Xlog:gc -jar YourApp.jar
  • -XX:+UnlockExperimentalVMOptions:解锁实验性VM选项。

  • -XX:+UseZGC:使用ZGC垃圾收集器。

  • -Xlog:gc:开启GC日志。

九、结语

合理的JVM调优可以显著提升应用的性能和稳定性。不过,请记得调优是一个持续的过程,需要根据应用的具体表现来不断调整和优化。

最后由于版本不断更新,JVM参数和具体说明,建议需要时请参考 oracle 官网的手册。

图片

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/324607.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Docker 容器之间的互相通信

Docker容器之间的互相通信 步骤一:创建自定义网络 首先,我们需要创建一个自定义网络,以便容器可以连接到这个网络上,从而实现互相通信。在命令行中执行以下命令: # 创建 docker network create ddz # 查看 docker n…

O2066PM无线WIFI6E网卡Windows环境吞吐测试

从2023年开始,除手机外的无线终端设备也逐步向WIFI6/6E进行升级更新,基于802.11ax技术的设备能够进一步满足用户体验新一代Wi-Fi标准时获得优质的性能和覆盖范围。 用户对于WIFI模块,通常会关注WIFI模块的吞吐量,拿到样品之后&am…

如何在iPhone或iPad中截取长页面,这里有详细步骤

iOS有太多隐藏的功能,记住它们可能是一个挑战,但知道如何在iPhone或iPad上截屏整个页面是我从未忘记的。 你若是一名作家,你经常会发现自己需要截屏网站和文章中的大块文本,以便发送给某人或稍后阅读。虽然现在的手机有着令人羡慕…

python统计分析——生成正态分布随机数

参考资料:用python动手学统计学,帮助文档 方法1:scipy.stats.norm.rvs() from scipy import stats stats.norm.rvs(loc4,scale0.8,size10) 参数介绍如下: loc:表示正态分布的均值,默认为0 scale&#…

Visual Studio Code常用设置

此处用于记录下本人所使用 VScode 的使用习惯。其中主要包括:界面,主题,光标,文件保存等选项。 VSCode 用户区设置 相关介绍命令行方式进行配置可视化组件方式进行配置 更新 相关介绍 基本原理: Visual Studio Code 会…

sizeof与strlen的使用及其区别

目录 1. sizeof 1.1sizeof简介 1.2 sizeof的使用 1.3 sizeof的使用注意事项 1.4 sizeof用于数组 2.strlen()函数 3.区别 示例1 示例2 示例3 4.总结 1. sizeof 1.1sizeof简介 sizeof是一个编译时运算符,可用于任何变量名、类型名…

Realm Management Extension领域管理扩展之系统架构

RME不仅仅是一组处理器功能,为了充分利用RME引入的功能,系统的其余部分需要提供支持。 下图显示了一个示例系统以及引入RME后受到影响的组件: 主存储器保护 RME启用的系统包括内存加密和可能的完整性。基线加密要求支持对外部内存进行加密,使用每个PA空间的单独加密密钥或…

1131. 拯救大兵瑞恩(dp思想运用,set)

1131. 拯救大兵瑞恩 - AcWing题库 1944 年,特种兵麦克接到国防部的命令,要求立即赶赴太平洋上的一个孤岛,营救被敌军俘虏的大兵瑞恩。 瑞恩被关押在一个迷宫里,迷宫地形复杂,但幸好麦克得到了迷宫的地形图。 迷宫的…

文心一言 vs. ChatGPT:哪个更胜一筹?

文心一言 vs. ChatGPT:从简洁美到深度思考的文本生成之旅 近年来,文本生成工具的崛起使得人们在表达和沟通方面拥有了更多的选择。在这个领域中,文心一言和ChatGPT作为两个备受瞩目的工具,各自以独特的优势展现在用户面前。本文将…

Maven普通工程和web工程创建

文章目录 创建项目前设置maven工程前设置工作创建项目前--》设置utf-8配置maven参数Maven普通工程和web工程创建Maven简单工程第一步:File–New–Project 第二步:选择maven然后下一步:填写后询选择finish初始化maven工程目录简介maven简单工程…

单列的堆叠柱状图

目的 MSingleColumnStackBarChart类被设计用于创建只有单列的堆叠柱状图,用于血糖数据的统计。以下是封装这个类的目的的详细描述: 抽象复杂性: 通过创建MSingleColumnStackBarChart类,你将复杂的MPAndroidChart库的使用和配置封…

合并两个有序数组(简单)

一、题目 给你两个按 非递减顺序 排列的整数数组nums1和nums2,另有两个整数m和n,分别表示nums1和nums2中的元素数目。请你 合并 nums2到nums1中,使合并后的数组同样按 非递减顺序 排列。 注意: 最终,合并后数组不应由…

PyTorch——torchtext与PyTorch匹配的版本

一、匹配版本的对照表 二、按照对应版本的命令 例子: pip install torchtext0.9.1参考资料: Torchtext and PyTorch s Version Compatibility

第七在线荣获百灵奖 Buylink Awards 2023零售圈年度卓越服务商品牌

1月11日,由零售圈主办、20零售连锁协会协办、30零售行业媒体支持的中国零售圈大会暨2024未来零售跨年盛典在西安落下帷幕,在这个零售行业盛典中,第七在线凭借其高精尖产品和卓越的服务质量成功入选,并荣获了“百灵奖 Buylink Awar…

基于 IDEA 创建 Maven 的 Java SE 工程和 Java Web 工程

一、概念简介 Maven 工程相对之前的项目,多出一组 gavp 属性,gav 需要我们在创建项目的时候指定,p 有默认值,我们先行了解下这组属性的含义。 Maven 中的 GAVP 是指 GroupId、ArtifactId、Version、Packaging 等四个属性的缩写&am…

c语言嵌套循环

c语言嵌套循环 c语言嵌套循环 c语言嵌套循环一、c语言嵌套循环类型二、嵌套循环案例九九惩罚口诀 一、c语言嵌套循环类型 for(初始值;表达式;表达式) {for(初始值;表达式;表达式){代码} }int main() {for (…

Springboot3新特性:GraalVM Native Image Support和虚拟线程(从入门到精通)

说明:都知道,我是搞java的,最近搞c的算法和redis数据库比较多,所以对于以下文章,都是我自己这样认为的,各位看完之后,可尽情评论。 GraalVM Native Image Support 具体用法 以往文章&#xff…

基于SSM的项目监管系统设计与实现

末尾获取源码 开发语言:Java Java开发工具:JDK1.8 后端框架:SSM 前端:采用JSP技术开发 数据库:MySQL5.7和Navicat管理工具结合 服务器:Tomcat8.5 开发软件:IDEA / Eclipse 是否Maven项目&#x…

C#用Math.Round和double.TryParse方法实现四舍五入

目录 一、涉及到的知识点 1.double.TryParse()方法 2.Math.Round(Decimal, Int32) 方法 3.comboBox1没有选项 二、示例 1.源码 2.生成 一、涉及到的知识点 1.double.TryParse()方法 详见本文作者写的其他文章&#xff0…

C++(1) —— 基础语法入门

目录 一、C初识 1.1 第一个C程序 1.2 注释 1.3 变量 1.4 常量 1.5 关键字 1.6 标识符命名规则 二、数据类型 2.1 整型 2.2 sizeof 关键字 2.3 实型(浮点型) 2.4 字符型 2.5 转义字符 2.6 字符串型 2.7 布尔类型 bool 2.8 数据的输入 三…