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. 一 ...
随机推荐
- zeroMQ 4 java
自己最开始是在cloud foundry中接触过消息服务器(nats),或者说是消息中间件,也算是初步知道了一个消息服务器对于分布式的网络系统的重要性,后来自己也曾想过在一些项目中使用它,尤其是在一些 ...
- c++学习书籍推荐《超越C++标准库:Boost库导论》下载
<超越C++标准库Boost库导论>不仅介绍了Boost库的功能.使用方法及注意事项,而且还深入讨论了Boost库的设计理念.解决问题的思想和技巧以及待处理的问题.因此,本书是一本了解Bo ...
- C# 使用Quartz简单实例以及备忘
一.导入NuGet 二.创建一个类并实现接口Ijob,并实现该接口中的方法. using Buday.Gold.Cusumer.Lib; using Quartz; using System; us ...
- 一个简单的使用mock技术进行测试的例子
Account: public class Account { private String acountId; private long balance; public Account(String ...
- RabbitMQ从入门到精通(三)
目录 1. 自定义消费者使用 自定义消费端演示 2.消费端的限流策略 2.1 限流的场景与机制 2.2 限流相关API 2.3 限流演示 3. 消费端ACK与重回队列机制 3.1 ACK与NACK 3 ...
- vscode在win10 / linux下的.vscode文件夹的配置 (c++/c)
系统方面配置自行查找 linux: launch.json { // 使用 IntelliSense 了解相关属性. // 悬停以查看现有属性的描述. // 欲了解更多信息,请访问: https:// ...
- [opengl] 画一个可移动的自行车 二维几何变换(平移、旋转、缩放)
#include <cmath> #include "glut.h" #include "iostream" using namespace std ...
- 《VR入门系列教程》之19---GearVR开发初识
本章我们来介绍一下如何在移动VR设备的佼佼者GearVR上进行开发,之前我们在桌面端的VR开发想法可以直接应用在移动端,但是仍然会有些不一样的技术需要注意.这次,我们仍然采用Unity3D引擎构建示例 ...
- PHP 跨域处理
PHP 跨域处理 跨域访问失败是会出现 No 'Access-Control-Allow-Origin' header is present on the requested resource. Or ...
- gRPC in ASP.NET Core 3.0 -- Protocol Buffer(1)
现如今微服务很流行,而微服务很有可能是使用不同语言进行构建的.而微服务之间通常需要相互通信,所以微服务之间必须在以下几个方面达成共识: 需要使用某种API 数据格式 错误的模式 负载均衡 ... 现在 ...