Spark Tungsten项目是Spark2.0开始引入的一个性能项目,Spark2.x也正式凭借Tungsten项目使其性能高于Spark1.x数倍,那么到底什么是Tungsten?Tungsten又是怎么让Spark性能提升如此之多?未来几周,我会对Tungsten进行深入讲解,让Tungsten没有秘密可言。
在开始之前,首先做几个约定:
1,本系列所有技术都是基于Spark2.2
2,所有的资源调度模式都是on yarn
3,所有的运行环境都是jdk1.8,scala 2.11.11
4,每个图片括号括起来的是代码的路径
5,这些技术或是本人在工作中,或是在对源码研究中的一些理解,由于本人能力有限,如果有什么错误的地方请大家能够及时指出
StaticMemoryManager比较简单,就不去讲述,我们主要是讲UnifiedMemoryManager,有兴趣的同学可以自己下去看看StaticMemoryManager
在讲UnifiedMemoryManager内存模型之前先来了解一下spark的内存在yarn上是怎么分配的:
(spark-default.conf)
11G?说好的8G怎么会多出3G?一个真理就是:如果有什么搞不懂的,就去看源码,源码能说明一切:
这里要注意,虽然spark向yarn申请的时候是3G内存,但实际启动executor的时候还是按照配置的2G来启动
再来看一个图:
这里的storage memory就是spark用来缓存rdd和shuffle数据的内存,也就是blockmanager分配到的内存,包括堆外和堆内两种,那么这个数据是怎么得来的?
我来翻译一下这段代码:
systemMemory=Runtime.getRuntime.maxMemory
RESERVED_SYSTEM_MEMORY_BYTES = 300 * 1024 * 1024
maxMemory=(systemMemory-reservedMemory)* memoryFraction=0.6(这里我采用的是默认值)
以上就是maxMemory也就是页面上显示的storage memory的计算方式,现在把具体数据带入公式就是:(systemMemory-300)* 0.6,唯一没有解决的是systemMemory值从哪儿来?还是来写一段代码:
执行一下
可以看到内存使用2048m输出的值是1981(不同的jdk,不同的操作系统输出可能不一样),这个1981就是年轻代+老年代的值,注意这里年轻代只计算了eden+一个space的值,最后把1981带入上面所说的计算公式可以得出maxMemory的最终值是1008.6m,为了验证这个值是否正确,可以查看spark的启动日志:
这行日志是blockmanager启动的时候向blockmanagermaster注册打印的,有点误差属于正常
细心的同学可能发现这里已经存在了一个问题,就是通过上面得出的值是1008.9,这个值不等于页面上显示的1.1G啊?那页面上显示的1.1G到底是怎么来的了?其实这个问题也困扰了我很久,查看了很久的代码才找到(主要是前端技术已经退化,现在再去看前端代码有点吃力了)
(utils.js)
页面上显示的storage memory值就是通过这个js方法算出来的,这里不知道是spark的bug还是有意为之的,后端计算用的计量单位是1024,到了前端就变成了1000,把1008.9*1024*1024传进去执行结果正好是1.1G
本文主要讲了两点:spark on yarn如何申请内存和UnifiedMemoryManager的storage memory是如何计算而来,搞明白了这两点就为接下来的知识点做好了铺垫,下面的文章我将重点讲解UnifiedMemoryManager的内存结构和spark是如何使用UnifiedMemoryManager内存的
领取专属 10元无门槛券
私享最新 技术干货