JVM调优之经验
在生产系统中,高吞吐和低延迟一直都是JVM调优的最终目标,但这两者恰恰又是相悖的,鱼和熊掌不可兼得,所以在调优之前要清楚舍谁而取谁。一般计算任务和组件服务会偏向高吞吐,而web展示则偏向低延迟才会带来更好的用户体验。
本文从性能和经验上来分享一下JVM参数的设置。
调优之前可以先用-XX:+PrintFlagsFinal来查看虚拟机是否默认开启某参数,不同版本的JDK可能虚拟机默认开启的参数也略有不同,新学习一条神奇的参数的时候可以先去查找一下参数是否默认开启了。
$ java -server -XX:+PrintCommandLineFlags |grep XXXXXXX
也可以通过jinfo口令 jinfo -flags [pid]
来查看
GC策略
目前来看还是CMS当道,吞吐率和响应时间阔以兼顾,G1嘛,鸡丸鸡丸,至今并没有展现出one的实力,不过据贵里某P8讲G1在大堆(20G+)下表现更突出,停顿会显著降低,可能之后随着高内存越来越经济和普及,G1才能名副其实的称为鸡one。
废话少说,
-XX:+UseConcMarkSweepGC
设置CMS做为垃圾收集,CMS开启后默认的新生代回收是ParNew,如果CMS出现“Concurrent Mode Failure”了还会启用Serial Old做备胎。
-XX:CMSInitiatingOccupancyFraction=75
默认值是68,这个可以根据实际调优目标来调整,这个参数就比较应开始提到的,调优目标是降低延迟还是提高吞吐,如果是为了降低单次GC延迟,那么这个值阔以再往低了调一些,不过调的太高可能导致老年代剩余空间不够招呼并发收集产生的浮动垃圾而频繁的触发Full GC。
-XX:+UseCMSInitiatingOccupancyOnly
使用CMS的话这个参数一定要加上,一定要加上,一定要加上,重要的事情说三遍,否则虚拟机后面还是会自作聪明的自己计算上个参数的比值。
-XX:MaxTenuringThreshold=5
默认15,这个值是设置新生代对象存活了多少次young GC后可以进入老年代,值设的高的话可以使老年代增长缓慢,但YGC的次数会明显增多,如果清楚YGC的执行频率和大多数对象的最长生命周期,这个值可以设低些,让那些对象早点进入老年代。
可以用-XX:+PrintTenuringDistribution
来观察一段时间,然后调整合适的值。
ps:有一种野路子是此值设为0,新生代GC次数少,速度快,就是老年代GC会更加频繁一些,不过也最大利用了并发GC。不过我没在生产这么搞过,效果有待验证。
-XX:+ExplicitGCInvokesConcurrent
这个参数是用来代替,-XX:DisableExplicitGC
的,NIO许多地方会显示的调用System.gc()来触发一次Full GC。许多时候别的地方优化一万点都赔不起这儿调上几次的。ExplicitGCInvokesConcurrent这个参数是配合CMS使用的,开启后System.gc()还是会触发Full GC,不过并不是一个完全的stop-the-world的Full GC,而是并发的CMS GC。
内存设置
现在线上业务系统基本物理内存都是够用的,不过物尽其用,我们调优就是争取让每M空间都发挥出最大的作用。内存的设置还是最直观见效的。
-Xmx500m ,-Xms500m
最大堆内存和最小堆内存,这两个值要设的一致,避免虚拟机还要动态的计算分配内存空间。
PS:堆也不是越大越好,大堆带来的后果就是单次GC会较长。
-Xmn250m
新生代大小,非G1收集器可以设置这个值,G1的官方建议是不要显示分配新生代和老年代空间大小,因为G1会通过网格化内存来动态分配new/old区,官方认为不设置new size是最佳实践。
-Xss2m
每个线程的栈空间大小,默认值是1m,一般不需要设置,除非有递归方法存在可能会爆栈。
-XX:PermSize=128m,-XX:MaxPermSize=256m
JDK8之前永久代的空间设置,Spring框架了大量依赖AOP的实现都用的动态代理生成字节码,所以设个最大值求保险。
不过JDK8之后取消了永久代,改为元空间(MetaSpace),这块属于本地内存,理论上可以利用系统剩余的所有内存,不过跑了多个实例的话还是要设置一下为妙:
-XX:MetaspaceSize=128m,-XX:MaxMetaspaceSize=256m
-XX:MaxDirectMemorySize=128m
这个属于对外内存,可以合理控制大小。Heap区总内存减去一个Survivor区的大小,不宜过大,否则可能heap size + Direct Memory Size
把物理内存耗光。
-XX:SurvivorRatio=7
默认是8,新生代中Eden与Survivor的比值,过大的话可能Survivor存不下临时对象而频繁触发分配担保。可以根据GC日志看实际情况。
PS:
关于内存大小的设置完全要根据各个机器和应用自身的情况来设置。
可以通过jstat -gc [pid] 2000 30
,每2s输出一次一共输出30次内存情况,看看各个区域增长的速度,最大空间等数据来修改内存设置。
监控输出
监控参数还是需要的,不然有时候线上偶尔OOM了真的不好重现。
-XX:+HeapDumpOnOutOfMemoryError,-XX:HeapDumpPath={path}
OOM的时候会输出dump快照到{path}目录,只需要指向目录,文件名JVM会保持唯一性。
-XX:+PrintGCDetails,-Xloggc:logs/gc.log,-XX:+PrintGCTimeStamps,-XX:+PrintGCDateStamps
打印GC详细记录,-XX:+PrintGC
这个口令是简单GC日志,为了更容易定位问题,我们开启Details模式,-Xloggc
是把gc日志输出到指定文件。
-XX:+PrintGCTimeStamps
显示的时间代表JVM启动至记录日志的时间。
-XX:+PrintGCDateStamps
则会添加上每行信息的绝对日期。
其实开启了-Xloggc
的话会隐式的开启-XX:+PrintGCTimeStamps
,不过为了防止各版本JVM改动差异,还是显示的设置出来保险。
-XX:-OmitStackTraceInFastThrow
这是个比较容易被忽略的参数,而没有经验的话又往往很难定位到原因。
JDK5之后JVM对异常做了一个优化,对于一些频繁抛出的异常,JIT重新编译后会抛出没有堆栈信息的异常,-server
模式下是默认开启的,因此在频繁抛出某个异常一段时间后,该优化开始起作用,即只抛出没有堆栈的异常信息。
但由于该优化是JIT编译后才启用的,所以开始该异常的抛出是有完整堆栈信息的,但运行一段时间可能发现没有任何堆栈信息,很难定位,初次遇到很容易摸不到头脑。
可以使用-XX:-OmitStackTraceInFastThrow
来关闭该项优化。
原文链接来源:lousama
JVM调优之经验的更多相关文章
- JVM调优(二)经验参数设置
调优设置具体解析 堆大小设置 JVM 中最大堆大小有三方面限制:相关操作系统的数据模型(32-bt还是64-bit)限制:系统的可用虚拟内存限制:系统的可用物理内存限制.32位系统下,一般限制在1.5 ...
- JVM调优的几种策略(转)
JVM参数调优是一个很头痛的问题,可能和应用有关系,别人说可以的对自己不一定管用.下面是本人一些JVM调优的实践经验,希望对读者能有帮助,环境LinuxAS4,resin2.1.17,JDK6.0,2 ...
- jmeter --JVM调优设置
JMeter用户可根据运行的计算机配置,来适当调整JMeter.bat中的JVM调优设置,如下所示: set HEAP=-Xms512m -Xmx512m set NEW=-XX:NewSize=12 ...
- 面试总问的jvm调优到底是要干什么?
1. 压力测试的理解,xxx的性能10w/s,对你有意义么? 没有那家卖瓜的会说自己家的不甜,同样,没有哪个开源项目愿意告诉你在对它条件最苛刻的时候压力情况是多少,一般官网号称给你看的性能指标都是在最 ...
- JVM调优参数、方法、工具以及案例总结
这种文章挺难写的,一是JVM参数巨多,二是内容枯燥乏味,但是想理解JVM调优又是没法避开的环节,本文主要用来总结梳理便于以后翻阅,主要围绕四个大的方面展开,分别是JVM调优参数.JVM调优方法(流程) ...
- jvm调优神器——arthas
在上一篇<jvm调优的几种场景>中介绍了几种常见的jvm方面调优的场景,用的都是jdk自带的小工具,比如jps.jmap.jstack等.用这些自带的工具排查问题时最大的痛点就是过程比较麻 ...
- Jvm调优理论篇
Jvm实战调优 OOM(Out Of Memory) 内存溢出错误 ps:由于Java虚拟机有许多实现,本文主要阐述的是OpenJDK的HotSpot虚拟机,JDK版本是8. 一.首先要明白造成OOM ...
- 高并发场景下JVM调优实践之路
一.背景 2021年2月,收到反馈,视频APP某核心接口高峰期响应慢,影响用户体验. 通过监控发现,接口响应慢主要是P99耗时高引起的,怀疑与该服务的GC有关,该服务典型的一个实例GC表现如下图: 可 ...
- 面试官问我JVM调优,我忍不住了!
面试官:今天要不来聊聊JVM调优相关的吧? 面试官:你曾经在生产环境下有过调优JVM的经历吗? 候选者:没有 面试官:... 候选者:嗯...是这样的,我们一般优化系统的思路是这样的 候选者:1. 一 ...
随机推荐
- 使用开源框架Sqlsugar结合mysql开发一个小demo
一.Sqlsugar简介 1.性能上有很大优势 sqlsugar是性能最好的ORM之一,具有超越Dapper的性能 ,走的是EMIT够构中间语言动态编译到程序集,完成高性能的实体绑定,达到原生水平. ...
- WeUI Picker组件 源代码分析
前言 由于最近做的一个移动端项目需要使用到类似 WeUI Picker组件 的选择效果, 所以在这里来分析下 WeUI Picker 的实现逻辑.(weui.js项目地址) 之前也做过类似的组件, ...
- NetCore AutoMapper的封装
需要引用AutoMapper的Nuget包 如果需要忽略某个字段就在字段上面打标签如下: [IgnoreMap] public string IgnoreValue { get; set; } ...
- GitHub代码阅读神器,你值有拥有!
(题图:from github) Github作为全球最大的程序员聚集地,已经成为学习开发技能的绝佳伴侣(如果你是程序员,但你还没有账户的话,这里建议你去signup,毕竟能增加成长的机会,不能错过 ...
- Single Thread Execution设计模式
public class Test { public static void main(String[] args){ // FlightSercurityTest.test(); // EatNoo ...
- Java读写二进制数据
import java.io.*; import java.time.LocalDate; public class Test { public static void main(String[] a ...
- 数据库系统概念:JDBC
import java.sql.*; public class DataBase { public static void main() { } } /* 5.1.1 JDBC */ class JD ...
- py+selenium 直接给日期赋值,控制台调试报错【已解决】
目标:给带日期控件的输入框赋值. 百度去搜索让你各种去只读readonly属性,再send_keys 方法: 其实既然可以去除readonly属性,那就可以直接给属性赋值,将两行代码缩为一行. dri ...
- [记录]FIO测试磁盘iops性能
FIO测试磁盘iops性能 1.SATA和SAS盘原生IOPS如下: 2.RAID磁盘阵列对应的写惩罚级别: 3.计算功能性IOPS公式如下: 功能性 IOPS=(((总原生 IOPS×写 %))/( ...
- Linux 系统的基本操作及工具的使用
基本操作命令如:useradd.userdel.passwd.su 添加用户.删除用户.修改密码.切换用户 ls.ll.cd.cp.mv.chmod ps.kil.man mkdir.touch.ta ...