文档章节

JVM调优示实例<一>

AbeJeffrey
 AbeJeffrey
发布于 2017/03/30 18:02
字数 1417
阅读 275
收藏 5

背景:

开发一个Spark Streaming job消费消息队列中的用户行为日志,job会源源不断处理消息队列中的消息。由于集群会运行很多job,现需要调整jvm参数优化job的运行。

下面是调优过程(基于java8):

首先设置VM参数如下 :

-Xmx256m -Xms256m -Xmn128m  -XX:SurvivorRatio=8 -XX:+UseParallelGC -XX:+UseParallelOldGC  

-XX:ParallelGCThreads=4  -XX:MaxMetaspaceSize=512m -XX:MaxTenuringThreshold=7  -XX:+PrintGCDetails 

参数注释 :

-Xmx256m:设置JVM最大堆内存为256m
-Xms256m:设置JVM初始堆内存为256m。将此值设置与-Xmx相同,以避免每次垃圾回收完成后JVM重新分配内存。
-Xmn128m: 设置堆内存年轻代大小为128m
-XX:SurvivorRatio=8 :设置堆内存年轻代中Eden区与Survivor区大小的比值 。设置为8,则两个Survivor区(JVM堆内存年轻代中默认有2个Survivor区)与一个Eden区的比值为2:8,一个Survivor区占整个年轻代的1/10。

-XX:+UseParallelGC :选择垃圾收集器为并行收集器。此配置仅对年轻代有效。

-XX:+UseParallelOldGC :配置年老代垃圾收集方式为并行收集。

-XX:ParallelGCThreads=4 :配置并行收集器的线程数,此值最好配置与处理器数目相等。

-XX:MaxMetaspaceSize=512m:设置元数据空间最大为512m,默认基本是无穷大,建议设置该参数,防止内存泄漏导致内存被无止境扩大,MaxMetaspaceSize并不会在jvm启动的时候分配一块这么大的内存出来,而java8之前MaxPermSize是会分配一块这么大的内存的。

-XX:MaxTenuringThreshold=7:表示一个对象如果在Survivor区移动7次还没有被回收就放入年老代。

1如果设置为0的话,则年轻代对象不经过Survivor区,直接进入年老代,对于年老代比较多的应用,这样做可以提高效率。

2如果将此值设置为一个较大值,则年轻代对象会在Survivor区进行多次复制,这样可以增加对象在年轻代存活时间,增加对象在年轻代即被回收的概率。

-XX:+PrintGCDetails : 输出GC详细信息

参数设置完成后,启动应用就报错 :

Exception in thread "main" java.lang.IllegalArgumentException: System memory 255328256 must be at least 4.718592E8. Please use a larger heap size.

    at org.apache.spark.memory.UnifiedMemoryManager$.getMaxMemory(UnifiedMemoryManager.scala:193)

    at org.apache.spark.memory.UnifiedMemoryManager$.apply(UnifiedMemoryManager.scala:175)

    at org.apache.spark.SparkEnv$.create(SparkEnv.scala:354)

    at org.apache.spark.SparkEnv$.createDriverEnv(SparkEnv.scala:193)

    at org.apache.spark.SparkContext.createSparkEnv(SparkContext.scala:288)

    at org.apache.spark.SparkContext.<init>(SparkContext.scala:457)

    at org.apache.spark.streaming.StreamingContext$.createNewSparkContext(StreamingContext.scala:874)

    at org.apache.spark.streaming.StreamingContext.<init>(StreamingContext.scala:81)

    at WebConsumer$.main(WebConsumer.scala:46)

    at WebConsumer.main(WebConsumer.scala)

查看Spark源码,发现初始化SparkContext默认需要的最小系统内存为450M;

修改参数为 :

-Xmx512m -Xms512m -Xmn256m -XX:SurvivorRatio=8 -XX:+UseParallelGC -XX:+UseParallelOldGC  

-XX:ParallelGCThreads=4  -XX:MaxMetaspaceSize=512m -XX:MaxTenuringThreshold=7  -XX:+PrintGCDetails 

正常启动应用,观察GC日志输出 :

[GC (Metadata GC Threshold) [PSYoungGen: 202202K->16781K(276480K)] 202202K->16870K(493568K), 0.0191049 secs] [Times: user=0.02 sys=0.00, real=0.02 secs] 

[Full GC (Metadata GC Threshold) [PSYoungGen: 16781K->0K(276480K)] [ParOldGen: 88K->16149K(217088K)] 16870K->16149K(493568K), [Metaspace: 20836K->20836K(1067008K)], 0.0395959 secs] [Times: user=0.08 sys=0.00, real=0.04 secs] 

[GC (Metadata GC Threshold) [PSYoungGen: 133458K->15592K(276480K)] 149608K->31749K(493568K), 0.0240460 secs] [Times: user=0.05 sys=0.00, real=0.02 secs] 

[Full GC (Metadata GC Threshold) [PSYoungGen: 15592K->0K(276480K)] [ParOldGen: 16157K->19444K(217088K)] 31749K->19444K(493568K), [Metaspace: 35073K->35073K(1079296K)], 0.0641864 secs] [Times: user=0.19 sys=0.00, real=0.06 secs] 

分析:应用刚启动完成则进行了两次Full GC,观察GC日志,此时Old使用率非常低,代码中也没用触发full GC的动作,日志中导致GC的原因是Metadata GC Threshold,因此可以确定由Metadata导致。那么需要优化元数据空间大小。根据GC日志可知,元数据空间达到20.8M则进行了一次,达到35M时又进行了一次,分析可能由于MetaspaceSize大小导致。

java8中MetaspaceSize默认20.8M左右,主要是控制metaspaceGC发生的初始阈值,也是最小阈值,但是触发metaspaceGC的阈值是不断变化的。因此这里最好设置一个合适的初始MetaspaceSize。

根据运行分析我的应用,发现metaspace达到60M左右后增长将非常缓慢,因此修改JVM参数,使用MetaspaceSize设置元数据空间初始容量为64M。现在的参数如下 :

-Xmx512m -Xms512m -Xmn256m -XX:SurvivorRatio=8 -XX:+UseParallelGC -XX:+UseParallelOldGC  
-XX:ParallelGCThreads=4  -XX:MetaspaceSize=64m -XX:MaxMetaspaceSize=512m -XX:MaxTenuringThreshold=7  -XX:+PrintGCDetails 

运行后发现程序没有发生Full GC,继续观察,发现Old区内存占用非常小,而Young区变化非常大,尤其在繁忙期间,伴随着多次minor gc发生。此时考虑增大堆内存年轻代大小。

再次修改参数为 :

-Xmx512m -Xms512m -Xmn400m -XX:SurvivorRatio=8 -XX:+UseParallelGC -XX:+UseParallelOldGC  
-XX:ParallelGCThreads=4  -XX:MetaspaceSize=64m -XX:MaxMetaspaceSize=512m -XX:MaxTenuringThreshold=7  -XX:+PrintGCDetails

运行程序,发现程序运行平稳,发生 minor gc次数也大量减少了。

总结:整个调优过程是不断修改jvm参数,观察运行情况,一步步测试出来的。从来就没有最优的配置,配置需根据应用的运行情况,环境资源限制,性能目标等多种因素决定。正如该示例,首先设置一些预估参数,然后观察GC日志,并结合工具(本示例主要使用Java自带工具jvisualvm)分析;然后调整参数,再次运行并分析,最终得出满足应用需求的配置参数。由于该应用中Old区中的对象相对固定且较小,大多数对象都是朝生夕灭,因此old区设置的堆空间相对较小 。

欢迎指出本文有误的地方,转载请注明原文出处https://my.oschina.net/7001/blog/871011

© 著作权归作者所有

下一篇: GC日志参数详解
AbeJeffrey
粉丝 43
博文 43
码字总数 116095
作品 0
杭州
高级程序员
私信 提问
加载中

评论(1)

wonderWang
wonderWang
给力👍
JVM性能优化, Part 5:Java的伸缩性

ImportNew注: JVM性能优化系列文章前4篇由ImportNew翻译(第一篇,第二篇,第三篇, 第四篇)。本文由新浪微博:吴杰 (@WildJay) 投稿至ImportNew。感谢吴杰! 如果你希望分享好的原创文章或...

梁杰_Jack
2014/10/30
224
0
《成神之路-基础篇》JVM——JVM参数及调优(已完结)

Java内存模型,Java内存管理,Java堆和栈,垃圾回收 本文是[《成神之路系列文章》][1]的第一篇,主要是关于JVM的一些介绍。 持续更新中 JVM参数及调优 JVM实用参数系列 成为Java GC专家(5)...

2018/05/05
0
0
成为Java GC专家(5)—Java性能调优原则

这是“成为Java GC专家”系列的第五篇文章。在第一篇深入浅出Java垃圾回收机制中,我们已经学习了不同的GC算法流程、GC的工作原理、新生代(Young Generation)和老年代(Old Generation)的...

stefanzhlg
2014/12/05
1K
1
JVM参数调优:Eclipse启动实践

JVM参数调优:Eclipse启动实践 本文主要参考自《深入理解 Java 虚拟机》。 这本书是国人写的难得的不是照搬代码注释的且不是废话连篇的技术书,内容涵盖了 Java 从源码到字节码到执行的整个过...

天天顺利
2015/01/13
281
0
JavaOne 2016 —— 首日亮点

今年,为期5天的JavaOne会议中,4个会场的议题都进行了直播,演讲稿也在播出之后一并提供。来自Terracotta公司EHCache团队的Henri Tremblay,做了主题为 《学习Java 8:Lambda表达式和函数式...

两味真火
2016/10/01
1K
3

没有更多内容

加载失败,请刷新页面

加载更多

读书笔记:深入理解ES6 (五)

第五章 解构:使数据访问更便捷 第1节 为什么使用解构功能?   在ES5中,开发者们从对象、数组中获取特定数据并赋值给变量,编写了很多看起来同质化的代码。例如: 1 let options = {2 ...

张森ZS
29分钟前
24
0
CentOS7 yum方式安装MySQL5.7

在CentOS中默认安装有MariaDB,这个是MySQL的分支,但为了需要,还是要在系统中安装MySQL,而且安装完成之后可以直接覆盖掉MariaDB。 1 下载并安装MySQL官方的 Yum Repository [root@localho...

roockee
38分钟前
15
0
Allegro三种自定义设置快捷键的方法

Allegro自定义设置快捷键的三种方法: 1、在Allegro PCB editor 命令窗口直接定义 2、通过修改用户变量env文件来设置快捷键 3、定义笔画为快捷键 1、在Allegro PCB editor 命令窗口直接定义 ...

demyar
42分钟前
18
0
如何做一张能让人眼前一亮的大屏?

作为在职场驰骋的社会人,提到数据可视化大家应该都不陌生了。数据可视化的作用也不用我多说,主要是利用图形化手段,更清晰直观地将数据展示。多层次、交互式的可视化分析能够方便决策者理解...

朕想上头条
43分钟前
9
0
TL138/1808/6748-EthEVM开发板硬件CPU、FLASH、RAM

TL138/1808/6748-EthEVM是广州创龙基于SOM-TL138/1808/6748核心板开发的一款开发板,具有三个网络接口。由于SOM-TL138/1808/6748核心板管脚兼容,所以此三个核心板共用同一个底板。开发板采用...

Tronlong创龙
47分钟前
16
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部