JVM调优之经验

摘要:
在生产系统中,高吞吐和低延迟一直都是JVM调优的最终目标,但这两者恰恰又是相悖的,鱼和熊掌不可兼得,所以在调优之前要清楚舍谁而取谁。本文从性能和经验上来分享一下JVM参数的设置。其实开启了-Xloggc的话会隐式的开启-XX:+PrintGCTimeStamps,不过为了防止各版本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调优之经验》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Ansible进阶C#返回多个参数 ref及out下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

从jvm的角度来看java的多线程

最近在学习jvm,发现随着对虚拟机底层的了解,对java的多线程也有了全新的认识,原来一个小小的synchronized关键字里别有洞天。决定把自己关于java多线程的所学整理成一篇文章,从最基础的为什么使用多线程,一直深入讲解到jvm底层的锁实现。 多线程的目的 为什么要使用多线程?可以简单的分两个方面来说: 在多个cpu核心下,多线程的好处是显而易见...

【转】asp.net(c#)使用HttpWebRequest附加携带请求参数以post方式模拟上传大文件(以图片为例)到Web服务器端

原文地址:http://docode.top/Article/Detail/10002 目录: 1、Http协议上传文件(以图片为例)请求报文体内容格式 2、完整版HttpWebRequest模拟上传文件请求报文内容封装 3、asp.net(c#)使用HttpWebRequest携带请求参数模拟上传文件封装源码下载 一、Http协议上传文件(以图片为例)...

JVM(三)JVM对象创建与内存分配机制学习

一、对象创建的过程 我们先画一个流程图来看一下对象在创建的过程中,经历了哪些步骤: 类加载检查   虚拟机遇到一条new指令时,首先将去检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并且检查这个符号引用代表的类是否已被加载、解析和初始化过。如果没有,那就会先执行相应的类加载过程。 分配内存   在类加载检查通过后,接下来虚拟机将为新生对象...

Java基础知识提要

1、简述Java的基本历史 java起源于SUN公司的一个GREEN的项目,其原先目的是:为家用消费电子产品发送一个信息的分布式代码系统,通过发送信息控制电视机、冰箱等 2、简单写出Java特点,写出5个以上,越多越好 简单的、面向对象的、分布式的、安全的、稳定的、与平台无关的、可解释的、多线的、动态的语言。 3、什么是Java? JAVA:一种编程...

18-MySQL DBA笔记-MySQL Server调优

第18章 MySQL Server调优 本章将为读者介绍针对MySQL Server的优化,这也是DBA最熟悉的领域之一。首先我们介绍MySQL的主要参数,然后,讲述常见硬件资源的优化。我们假设读者已经具备了足够的基础知识,所以,本章将更多的针对一些特定的主题进行叙述。18.1 概述 衡量数据库性能的指标,一般衡量数据库的性能有两个指标:响应时间和吞吐率。...

Tomcat的JVM设置和连接数设置

Windows环境下修改“%TOMCAT_HOME%\bin\catalina.bat”文件,在文件开头增加如下设置:set JAVA_OPTS=-Xms256m -Xmx512m Linux环境下修改“%TOMCAT_HOME%\bin\catalina.sh”文件,在文件开头增加如下设置:JAVA_OPTS=’-Xms256m -Xmx512m’...