JVM性能调优详解

news2024/10/6 6:46:08

前面我们学习了整个JVM系列,最终目标的不仅仅是了解JVM的基础知识,也是为了进行JVM性能调优做准备。这篇文章带领大家学习JVM性能调优的知识。

性能调优

性能调优包含多个层次,比如:架构调优、代码调优、JVM调优、数据库调优、操作系统调优等。

架构调优和代码调优是JVM调优的基础,其中架构调优是对系统影响最大的。

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

何时进行JVM调优

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

Heap内存(老年代)持续上涨达到设置的最大内存值;
Full GC 次数频繁;
GC 停顿时间过长(超过1秒);
应用出现OutOfMemory 等内存异常;
应用中有使用本地缓存且占用大量内存空间;
系统吞吐量与响应性能不高或下降。

JVM调优的基本原则

JVM调优是一个手段,但并不一定所有问题都可以通过JVM进行调优解决,因此,在进行JVM调优时,我们要遵循一些原则:

大多数的Java应用不需要进行JVM优化;
大多数导致GC问题的原因是代码层面的问题导致的(代码层面);
上线之前,应先考虑将机器的JVM参数设置到最优;
减少创建对象的数量(代码层面);
减少使用全局变量和大对象(代码层面);
优先架构调优和代码调优,JVM优化是不得已的手段(代码、架构层面);
分析GC情况优化代码比优化JVM参数更好(代码层面);
通过以上原则,我们发现,其实最有效的优化手段是架构和代码层面的优化,而JVM优化则是最后不得已的手段,也可以说是对服务器配置的最后一次“压榨”。

JVM调优目标

调优的最终目的都是为了令应用程序使用最小的硬件消耗来承载更大的吞吐。jvm调优主要是针对垃圾收集器的收集性能优化,令运行在虚拟机上的应用能够使用更少的内存以及延迟获取更大的吞吐量。

延迟:GC低停顿和GC低频率;
低内存占用;
高吞吐量;
其中,任何一个属性性能的提高,几乎都是以牺牲其他属性性能的损为代价的,不可兼得。具体根据在业务中的重要性确定。

JVM调优量化目标

下面展示了一些JVM调优的量化目标参考实例:

Heap 内存使用率 <= 70%;
Old generation内存使用率<= 70%;
avgpause <= 1秒;
Full gc 次数0 或 avg pause interval >= 24小时 ;
注意:不同应用的JVM调优量化目标是不一样的。

JVM调优的步骤

一般情况下,JVM调优可通过以下步骤进行:

分析GC日志及dump文件,判断是否需要优化,确定瓶颈问题点;
确定JVM调优量化目标;
确定JVM调优参数(根据历史JVM参数来调整);
依次调优内存、延迟、吞吐量等指标;
对比观察调优前后的差异;
不断的分析和调整,直到找到合适的JVM参数配置;
找到最合适的参数,将这些参数应用到所有服务器,并进行后续跟踪。
以上操作步骤中,某些步骤是需要多次不断迭代完成的。一般是从满足程序的内存使用需求开始的,之后是时间延迟的要求,最后才是吞吐量的要求,要基于这个步骤来不断优化,每一个步骤都是进行下一步的基础,不可逆行之。

JVM参数

JVM调优最重要的工具就是JVM参数了。先来了解一下JVM参数相关内容。

-XX 参数被称为不稳定参数,此类参数的设置很容易引起JVM 性能上的差异,使JVM存在极大的不稳定性。如果此类参数设置合理将大大提高JVM的性能及稳定性。

不稳定参数语法规则包含以下内容。

布尔类型参数值:

-XX:+ '+'表示启用该选项
-XX:- '-'表示关闭该选项
数字类型参数值:

-XX:=

给选项设置一个数字类型值,可跟随单位,例如:'m’或’M’表示兆字节;'k’或’K’千字节;'g’或’G’千兆字节。32K与32768是相同大小的。
字符串类型参数值:

-XX:=
给选项设置一个字符串类型值,通常用于指定一个文件、路径或一系列命令列表。例如:-XX:HeapDumpPath=./dump.core

JVM参数解析及调优

比如以下参数示例:

-Xmx4g –Xms4g –Xmn1200m –Xss512k -XX:NewRatio=4 -XX:SurvivorRatio=8 -XX:PermSize=100m -XX:MaxPermSize=256m -XX:MaxTenuringThreshold=15
上面为Java7及以前版本的示例,在Java8中永久代的参数-XX:PermSize和-XX:MaxPermSize已经失效。这在前面章节中已经讲到。

参数解析:

  • -Xmx4g:堆内存最大值为4GB。
  • -Xms4g:初始化堆内存大小为4GB。
  • -Xmn1200m:设置年轻代大小为1200MB。增大年轻代后,将会减小年老代大小。此值对系统性能影响较大,Sun官方推荐配置为整个堆的3/8。
  • -Xss512k:设置每个线程的堆栈大小。JDK5.0以后每个线程堆栈大小为1MB,以前每个线程堆栈大小为256K。应根据应用线程所需内存大小进行调整。在相同物理内存下,减小这个值能生成更多的线程。但是操作系统对一个进程内的线程数还是有限制的,不能无限生成,经验值在3000~5000左右。
  • -XX:NewRatio=4:设置年轻代(包括Eden和两个Survivor区)与年老代的比值(除去持久代)。设置为4,则年轻代与年老代所占比值为1:4,年轻代占整个堆栈的1/5
  • -XX:SurvivorRatio=8:设置年轻代中Eden区与Survivor区的大小比值。设置为8,则两个Survivor区与一个Eden区的比值为2:8,一个Survivor区占整个年轻代的1/10
  • -XX:PermSize=100m:初始化永久代大小为100MB。
  • -XX:MaxPermSize=256m:设置持久代大小为256MB。
  • -XX:MaxTenuringThreshold=15:设置垃圾最大年龄。如果设置为0的话,则年轻代对象不经过Survivor区,直接进入年老代。对于年老代比较多的应用,可以提高效率。如果将此值设置为一个较大值,则年轻代对象会在Survivor区进行多次复制,这样可以增加对象再年轻代的存活时间,增加在年轻代即被回收的概论。
    新生代、老生代、永久代的参数,如果不进行指定,虚拟机会自动选择合适的值,同时也会基于系统的开销自动调整。

可调优参数:

-Xms:初始化堆内存大小,默认为物理内存的1/64(小于1GB)。

-Xmx:堆内存最大值。默认(MaxHeapFreeRatio参数可以调整)空余堆内存大于70%时,JVM会减少堆直到-Xms的最小限制。

-Xmn:新生代大小,包括Eden区与2个Survivor区。

-XX:SurvivorRatio=1:Eden区与一个Survivor区比值为1:1。

-XX:MaxDirectMemorySize=1G:直接内存。报java.lang.OutOfMemoryError: Direct buffer memory异常可以上调这个值。

-XX:+DisableExplicitGC:禁止运行期显式地调用System.gc()来触发fulll GC。

注意: Java RMI的定时GC触发机制可通过配置-Dsun.rmi.dgc.server.gcInterval=86400来控制触发的时间。

-XX:CMSInitiatingOccupancyFraction=60:老年代内存回收阈值,默认值为68。

-XX:ConcGCThreads=4:CMS垃圾回收器并行线程线,推荐值为CPU核心数。

-XX:ParallelGCThreads=8:新生代并行收集器的线程数。

-XX:MaxTenuringThreshold=10:设置垃圾最大年龄。如果设置为0的话,则年轻代对象不经过Survivor区,直接进入年老代。对于年老代比较多的应用,可以提高效率。如果将此值设置为一个较大值,则年轻代对象会在Survivor区进行多次复制,这样可以增加对象再年轻代的存活时间,增加在年轻代即被回收的概论。

-XX:CMSFullGCsBeforeCompaction=4:指定进行多少次fullGC之后,进行tenured区 内存空间压缩。

-XX:CMSMaxAbortablePrecleanTime=500:当abortable-preclean预清理阶段执行达到这个时间时就会结束。

在设置的时候,如果关注性能开销的话,应尽量把永久代的初始值与最大值设置为同一值,因为永久代的大小调整需要进行FullGC才能实现。

内存优化示例

当JVM运行稳定之后,触发了FullGC我们一般会拿到如下信息:
在这里插入图片描述

以上gc日志中,在发生fullGC之时,整个应用的堆占用以及GC时间。为了更加精确需多次收集,计算平均值。或者是采用耗时最长的一次FullGC来进行估算。上图中,老年代空间占用在93168kb(约93MB),以此定为老年代空间的活跃数据。则其他堆空间的分配,基于以下规则来进行。

java heap:参数-Xms和-Xmx,建议扩大至3-4倍FullGC后的老年代空间占用。
永久代:-XX:PermSize和-XX:MaxPermSize,建议扩大至1.2-1.5倍FullGc后的永久带空间占用。
新生代:-Xmn,建议扩大至1-1.5倍FullGC之后的老年代空间占用。
老年代:2-3倍FullGC后的老年代空间占用。
基于以上规则,则对参数定义如下:

java -Xms373m -Xmx373m -Xmn140m -XX:PermSize=5m -XX:MaxPermSize=5m

延迟优化示例
对延迟性优化,首先需要了解延迟性需求及可调优的指标有哪些。

  • 应用程序可接受的平均停滞时间: 此时间与测量的Minor
  • GC持续时间进行比较。可接受的Minor GC频率:Minor
  • GC的频率与可容忍的值进行比较。
  • 可接受的最大停顿时间:最大停顿时间与最差情况下FullGC的持续时间进行比较。
  • 可接受的最大停顿发生的频率:基本就是FullGC的频率。

其中,平均停滞时间和最大停顿时间,对用户体验最为重要。对于上面的指标,相关数据采集包括:MinorGC的持续时间、统计MinorGC的次数、FullGC的最差持续时间、最差情况下,FullGC的频率。
在这里插入图片描述

如上图,Minor GC的平均持续时间0.069秒,MinorGC的频率为0.389秒一次。

新生代空间越大,Minor GC的GC时间越长,频率越低。如果想减少其持续时长,就需要减少其空间大小。如果想减小其频率,就需要加大其空间大小。

这里以减少了新生代空间10%的大小,来减小延迟时间。在此过程中,应该保持老年代和持代的大小不变化。调优后的参数如下变化:

java -Xms359m -Xmx359m -Xmn126m -XX:PermSize=5m -XX:MaxPermSize=5m

吞吐量调优

吞吐量调优主要是基于应用程序的吞吐量要求而来的,应用程序应该有一个综合的吞吐指标,这个指标基于整个应用的需求和测试而衍生出来的。

评估当前吞吐量和目标差距是否巨大,如果在20%左右,可以修改参数,加大内存,再次从头调试,如果巨大就需要从整个应用层面来考虑,设计以及目标是否一致了,重新评估吞吐目标。

对于垃圾收集器来说,提升吞吐量的性能调优的目标就是尽可能避免或者很少发生FullGC或者Stop-The-World压缩式垃圾收集(CMS),因为这两种方式都会造成应用程序吞吐降低。尽量在MinorGC 阶段回收更多的对象,避免对象提升过快到老年代。

调优工具

借助GCViewer日志分析工具,可以非常直观地分析出待调优点。可从以下几方面来分析:

Memory,分析Totalheap、Tenuredheap、Youngheap内存占用率及其他指标,理论上内存占用率越小越好;

Pause,分析Gc pause、Fullgc pause、Total pause三个大项中各指标,理论上GC次数越少越好,GC时长越小越好;

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

最优二叉树(哈夫曼树)

一、最优二叉树 1、定义 官方定义&#xff1a;在权值为w1&#xff0c;w2&#xff0c;…&#xff0c;wn的 n个叶子所构成的所有二叉树中&#xff0c;带权路径长度最小(即代价最小)的二叉树称为最优二叉树或哈夫曼树。 通俗来讲&#xff0c;就是给定N个权值作为N个叶子结点&…

仿牛客论坛项目总结

一.数据库中每一张表有哪些字段 user表 用户表 &#xff08;1&#xff09;id 用户的id &#xff08;2&#xff09; username 用户名 &#xff08;3&#xff09;password 密码 &#xff08;4&#xff09;salt 盐 &#xff08;5&#xff09;emai邮箱 &#xff08;6&…

PAT甲级1008 Elevator C++/C语言

1008 Elevator 分数 20 作者 CHEN, Yue 单位 浙江大学 The highest building in our city has only one elevator. A request list is made up with N positive numbers. The numbers denote at which floors the elevator will stop, in specified order. It costs 6 seconds …

联邦学习将如何影响您的日常生活?

人工智能 (AI) 被认为是下一次工业革命的最大创新之一&#xff0c;其中包括机器学习。另一方面&#xff0c;随着原油和电力成为现代工业的基础资源&#xff0c;数据成为人工智能和机器学习的关键要素。 数据隐私与需求之间的冲突 训练的数据样本的大小决定了可用于增强 AI 性能…

CPT203-Software Engineering(2)

文章目录5. Scrum Framework5.1 Scrum Roles5.2 Scrum Activities and Artifacts6. Requirements Engineering6.1 User requirements and system requirements6.2 Functional & Non-functional requirements6.2.1 Functional requirements6.2.2 Non-functional requirement…

第一章:C++算法基础之基础算法

系列文章目录 文章目录系列文章目录前言一、排序&#xff08;1&#xff09;快速排序核心思想思路分析模板&#xff08;2&#xff09;归并排序核心思想思路分析模板稳定性时间复杂度二分查找&#xff08;1&#xff09;整数二分核心思想思路分析模板&#xff08;2&#xff09;浮点…

jetson nano系统引导安装(无外设安装方式)

文章目录一.硬件设置二.系统设置一.硬件设置 插入烧写好系统的SD卡将micro USB线接到jetson nano上&#xff0c;另一端USB A接到电脑上为jetson nano插入电源&#xff0c;开机等待电脑检测到如下盘符说明jetson nano连接成功 二.系统设置 进入电脑的设备管理器&#xff0c;查…

【linux】三种权限的使用和更改、粘滞位和yum的使用

目录 1.权限问题 ①什么是权限&#xff1f; ②小问题 ③默认权限 ④如何更改“人”的权限呢&#xff1f; ⑤更改权限的八进制方案 ⑥强制改权限里的“人”&#xff08;权限人文件属性&#xff09; 2.粘滞位 2.yum的使用 1.权限问题 ①什么是权限&#xff1f; 权限人&a…

HTTP协议解析

HTTP概述 HTTP (全称为 "超文本传输协议") 是一种应用非常广泛的应用层协议~~我们平时打开一个网站, 就是通过 HTTP 协议来传输数据的。 HTTP工作过程&#xff1a; 当我们在浏览器中输入一个 "网址"&#xff0c;此时浏览器就会给对应的服务器发送一个 H…

CTF中的PHP特性函数(上)

前言 对于PHP大家一定不陌生&#xff0c;但你知道PHP在CTF中是如何考察的吗&#xff0c;本文给大家带来的是通过PHP特性来进行CTF比赛中解题出题的知识&#xff0c;会介绍一下CTF中常见的php特性以及围绕该知识点的相关案例&#xff0c;因为内容过多这里分成上中下三篇来讲&am…

操作系统的特征

文章目录&#x1f380;前言&#xff1a;本篇博客知识总览&#x1f354;并发&#x1f387;概念&#xff1a;&#x1f354;共享&#x1f387;概念&#xff1a;&#x1f354;虚拟&#x1f387;概念&#xff1a;&#x1f354;异步&#x1f387;概念&#xff1a;&#x1f3f3;️‍&a…

ThinkPHP 多应用模式之Api路由分组+中间件

ThinkPHP 6.1 在多应用模式下实现API路由分组中间件验证业务 目录 1.创建中间件文件 2.迁移中间件到子应用目录中 3.编辑中间件验证业务 修改命名空间 编写handle处理代码 4.注册中间件 编辑中间件文件 TP内置中间件 5.设置路由分组 优化相同控制器前缀 最终效果&am…

【信息论与编码 沈连丰】第六章:连续信息和连续信道

【信息论与编码 沈连丰】第六章&#xff1a;连续信息和连续信道第六章 连续信息和连续信道6.1 连续消息的信息6.2 连续消息在信道上的传输问题6.3 香农信道容量公式6.4 连续消息的识别和理想接收机6.5 连续信源的数字处理及其编码第六章 连续信息和连续信道 6.1 连续消息的信息…

在 KubeSphere 上部署 OpenLDAP 并进行对接使用

在 KubeSphere 上部署 OpenLDAP 并进行对接-进阶背景前置条件KubeSphere 中部署 LDAP部署 LDAP 应用ApacheDirectoryStudio 验证 LDAP下载部署 ApacheDirectoryStudioApacheDirectoryStudio 测试 LDAP创建 Ldap Search &#xff0c;KS 对接时可选择使用KubeSphere 对接 LDAPHar…

【区块链 | EVM】深入理解学习EVM - 深入Solidity数据存储位置:内存

图片来源: Mech Mind on Unsplash 这是深入Solidity数据存储位置系列的另一篇。在今天的文章中,我们将学习EVM内存的布局,它的保留空间,空闲内存指针,如何使用memory引用来读写内存,以及使用内存时的常规最佳做法。 我们将使用 Ethereum Name Service (ENS)中的合约代码…

实模式和保护模式的区别

实模式和保护模式的区别 实模式和保护模式的来历 最早期的8086 CPU只有一种工作方式 ---- 实模式。数据总线为16位&#xff0c;地址总线为20位。实模式下所有寄存器都是16位。 从80286开始就有了保护模式&#xff0c;从80386开始CPU数据总线和地址总线均为32位&#xff0c;而且…

开发板测试手册——SPI FLASH 读写、USB WIFI 模块(2)

目录 1.8 SPI FLASH 读写测试 20 1.9 USB 接口读写测试 21 1.10 网络接口测试 23 1.10.1 网络连通测试 23 1.10.2 网络速度测试 25 2 网络静态 IP 设置 27 3 USB WIFI 模块测试 31 3.1 WIFI STA 功能测试 32 3.2 WIFI AP 功能测试 35 3.3 USB WIFI 驱动编译 39 前 言…

scikit-learn线性模型之线性回归

scikit-learn线性模型之线性回归线性回归参考文献线性回归 有监督学习中主要解决两个问题&#xff0c;一个是分类&#xff0c;另一个是回归。 在回归问题中&#xff0c;我们需要利用我们已知的特征 x1,x2,...,xpx_1,x_2,...,x_px1​,x2​,...,xp​ 去预测我们的目标变量 yyy 。…

隐私计算一体机,金融大数据规模商用的催化剂

一股隐私计算的浪潮正席卷金融行业。 银行通过隐私计算引入外部不动产数据&#xff0c;与行内贷款企业的时点贷款余额、注册资本等数据联合建立企业贷中预警监测模型&#xff0c;提升银行风险监测业务能力&#xff1b;银行利用联邦学习与互联网公司的客户特征数据完成联合建模…

Linux:使用telnet命令提示:Connection refused

我是 ABin-阿斌&#xff1a;写一生代码&#xff0c;创一世佳话&#xff0c;筑一览芳华。如果小伙伴们觉得不错就一键三连吧~ 下一篇&#xff1a;Linux安装telnet命令教程 文章目录一、分析没有xinetd服务&#xff1a;二、讲解&#xff1a; 什么是 telnet 命令具体语法具体参数三…