性能调优java
- 常规性能调优:分配资源、并行度。。。等
- JVM调优(Java虚拟机):JVM相关的参数,一般状况下,若是你的硬件配置、基础的JVM的配置,均可以的话,JVM一般不会形成太严重的性能问题;反而更多的是,在troubleshooting中,JVM占了很重要的地位;JVM形成线上的spark做业的运行报错,甚至失败(好比OOM)。
- shuffle调优(至关重要):spark在执行groupByKey、reduceByKey等操做时的,shuffle环节的调优。这个很重要。shuffle调优,其实对spark做业的性能的影响,是至关之高!!!经验:在spark做业的运行过程当中,只要一牵扯到有shuffle的操做,基本上shuffle操做的性能消耗,要占到整个spark做业的50%~90%。10%用来运行map等操做,90%耗费在shuffle操做。
- spark操做调优(spark算子调优,比较重要):有些算子的性能,是比其余一些算子的性能要高的。foreachPartition替代foreach。
若是一旦遇到合适的状况,效果仍是不错的。算法
一、分配资源、并行度、RDD架构与缓存
二、shuffle调优
三、spark算子调优
四、JVM调优、广播大变量。。。数据库JVM调优原理概述。api
JVM调优里面全部官方都推荐来下降cache操做占比缓存
- 理论基础:spark是用scala开发的。你们不要觉得scala就跟java一点关系都没有了,这是一个很常见的错误。spark的scala代码调用了不少java api。scala也是运行在java虚拟机中的。spark是运行在java虚拟机中的。java虚拟机可能会产生什么样的问题:内存不足??!!咱们的RDD的缓存、task运行定义的算子函数,可能会建立不少对象。均可能会占用大量内存,没搞好的话,可能致使JVM出问题。
- 堆内存:
- 存放咱们建立的一些对象,堆内存分为年轻带young generation和老年带old generation,年轻带内部又分为三块,Eden区域比较大,两个survivor区域比较小存活区域咱们在spark task执行算子函数(咱们本身写的针对RDD的操做),可能会建立不少对象,这些对象,都是要放入JVM年轻代中的。每一次放对象的时候,都是放入eden区域,和其中一个survivor区域;另一个survivor区域是空闲的。当eden区域和一个survivor区域放满了之后(spark运行过程当中,产生的对象实在太多了),就会触发minor gc,小型垃圾回收。垃圾回收器gc会把再也不使用的对象,从内存中清空,给后面新建立的对象腾出来点儿地方。
- 清理掉了再也不使用的对象以后,那么也会将存活下来的对象(还要继续使用的),放入以前空闲的那一个survivor区域中。这里可能会出现一个问题。默认eden、survior1和survivor2的内存占比是8:1:1。问题是,若是存活下来的对象是1.5,一个survivor区域放不下。此时就可能经过JVM的担保机制(不一样JVM版本可能对应的行为),将多余的对象,直接放入老年代了。
- 若是你的JVM内存不够大的话,可能致使频繁的年轻代内存满溢,频繁的进行minor gc。频繁的minor gc会致使短期内,有些存活的对象,屡次垃圾回收都没有回收掉。就是那些一直在用的又不能被释放的就频繁的倒来倒去!会致使这种短声明周期(其实不必定是要长期使用的)对象,每回收一次,年龄长一岁!年龄过大,垃圾回收次数太多尚未回收到,跑到老年代。
- 说白了就是短声明周期对象却跑到老年代里面去了!!!原本是短周期的,结果倒来倒去跑到老年代里面去了,理想状况下,老年代都是放一些生命周期很长的对象,数量应该是不多的。好比数据库链接池,数据库链接池原本就不多。
- 简而言之,老年代中,可能会由于内存不足,囤积一大堆,短生命周期的,原本应该在年轻代中的,可能立刻就要被回收掉的对象。此时,可能致使老年代频繁满溢。频繁进行full gc(全局/全面垃圾回收)。full gc就会去回收老年代中的对象。full gc因为这个算法的设计,是针对的是,老年代中的对象数量不多,满溢进行full gc的频率应该不多,所以采起了不太复杂,可是耗费性能和时间的垃圾回收算法。full gc很慢。
- full gc / minor gc,不管是快,仍是慢,都会致使jvm的工做线程中止工做,stop the world。简而言之,就是说,gc的时候,spark中止工做了。等着垃圾回收结束。
- 内存不充足的时候,问题:
- 频繁minor gc,也会致使频繁spark中止工做;
- 老年代囤积大量活跃对象(短生命周期的对象),致使频繁full gc,full gc时间很长,短则数十秒,长则数分钟,甚至数小时。可能致使spark长时间中止工做;
- 严重影响我们的spark的性能和运行的速度。
如何解决?架构
spark.storage.memoryFraction,0.6 -> 0.5 -> 0.4 -> 0.2
你们能够本身去调,而后观察spark做业的运行统计!!!而后看看总体运行时间有没有改善!gc是否频繁,gc时间等!上述比例均可以调!根据不一样需求来作!jvm
.set("spark.storage.memoryFraction", "0.5")