首先,要做JVM内存模型调优之前先好好审视你的代码质量!算法不行就改算法!!不要什么都交给调优!!!
Spark部分
摘抄自 https://www.ibm.com/developerworks/cn/analytics/library/ba-cn-apache-spark-memory-management/index.html
概述
首先要了解Spark的RDD,Shuffle,merge概念以及Spark的工作原理,stage划分和宽窄依赖等概念
- RDD
弹性分布式数据集,本质上是一个只读的分区记录集合。每个 RDD 可以分成多个分区,每个分区就是一个数据集片段。一个 RDD 的不同分区可以保存到集群中的不同结点上,从而可以在集群中的不同结点上进行并行计算。
为什么要设计RDD?
传统的MapReduce会不断重用中间结果,需要不断在磁盘中读写数据,开销比较大。
而RDD
- 中间结果是保存到内存中的,避免了不必要的内存开销
- 存放的对象可以是java,避免了对象的序列化和反序列化
- Shuffle
Shuffle描述着数据从map task输出到reduce task输入的这段过程。shuffle是连接Map和Reduce之间的桥梁,Map的输出要用到Reduce中必须经过shuffle这个环节,shuffle的性能高低直接影响了整个程序的性能和吞吐量。
具体来说,在分布式的情况下,reduce task需要跨节点去拉取其他节点上的map task的任务。这个过程其实会产生网络资源消耗,内存消耗和磁盘IO消耗。
通常Map阶段的数据准备和Reduce阶段的数据准备分别称为Shuffle Write和Shuffle Read.
Shuffle 过程本质上都是将 Map 端获得的数据使用分区器进行划分,并将数据发送给对应的 Reducer 的过程
- merge操作:
使用SortShuffleManager的时候,每个Task在进行shuffle操作时,虽然也会产生较多的临时磁盘文件,但是最后会将所有的临时文件合并(merge)成一个磁盘文件,因此每个Task就只有一个磁盘文件。Reduce机器的shuffle read task拉取自己的数据时,只要根据索引读取每个磁盘文件中的部分数据即可。
- spark执行过程
1.构建基本的运行环境,由driver创建一个SparkContext,分配并且监控资源的使用情况。
2.资源管理器为其分配资源,然后启动Executor进程
3.SparkContext根据RDD的依赖关系构建DAG图,DAG图提交给DAGScheduler解析成Stage,然后再提交给底层的taskscheduler,即executor向sparkContext申请task,task scheduler会把task发放给Executor运行并且提供应用程序代码
4.Task在Executor运行之后把结果反馈给TaskScheduler,一层层反馈上去最后释放资源。
- 宽依赖和窄依赖
窄依赖:父RDD的一个Partition最多被子RDD的一个Partition所使用,如map,filter操作
即rdd的每个partition仅仅对应父rdd中的一个partition
宽依赖:父RDD的Partition会被多个子RDD的Partition所使用,如GroupByKey,reduceByKey,join,sortByKey操作
之所以要划分窄依赖和宽依赖,主要是用来完成Stage的划分
从后往前:
如果RDD之间是窄依赖,就划分为一个stage内。
如果RDD之间是宽依赖,则断开,划分为不同的stage