Spark从1.6.0版本开始,内存管理模块就发生了改变,旧版本的内存管理模块是实现了StaticMemoryManager 类,现在被称为"legacy"。"Legacy"模式默认被置为不可用,这就意味着当你用Spark1.5.x和Spark1.6.x运行相同的代码会有不同的结果,应当多加注意。考虑的兼容性,可以通过设置spark.memory.useLegacyMode为可用,默认是false.

  这篇文章介绍自spark1.6.0版本后的新的内存管理模型,它实现的是UnifiedMemoryManager类。

在这张图中你可以看到三个主要内存区域。

1.Reserved Memory.这部分内存是被系统预留的,它的大小也是被硬编码的。在Spark1.6.0版本,它的大小是300MB,这就意味着这部分内存不能计入Spark内存计算,除非重新编译源码或设置spark.testing.reservedMemory,它的大小是不可改变的,因为park.testing.reservedMemory只是一个测试参数所以在生产中不推荐使用。注意,这部分内存只是被称为“Reserved",实际上它不会被spark用来干任何事情 ,但是它限制了你在spark中可分配的内存大小。即使你想将全部JVM堆内存用于spark缓存数据,也不能使用这部分空闲内存(不是真的就浪费了,其实它存储了Spark的一些内部对象)。供参考,如果你不能为executor至少1.5 * Reserved Memory = 450MB的堆内存,任务将会失败并提示”please use larger heap size“的错误信息。

2.User Memory.这部分内存是分配Spark Memory内存之后的部分,而且这部分用来干什么完全取决于你。你可以用来存储RDD transformations过程使用的数据结构。例如,你可以通过mapPartitions transformation 重写Spark aggregation,mapPartitions transformations 保存hash表保证aggregation运行。这部分数据就保存在User Memory。再次强调,这是User Memory它完全由你决定存什么、如何使用,Spark完全不会管你拿这块区域用来做什么,怎么用,也不会考虑你的代码在这块区域是否会导致内存溢出。

3.Spark Memory.这部分内存就是由Spark管理了。这部分内存大小的计算:(“Java Heap” – “Reserved Memory”) * spark.memory.fraction,而且在spark1.6.0版本默认大小为: (“Java Heap” – 300MB) * 0.75。例如:如果堆内存大小有4G,将有2847MB的Spark Memory,Spark Memory=(4*1024MB-300)*0.75=2847MB。这部分内存会被分成两部分:Storage Memory和Execution Memory,而且这两部分的边界由spark.memory.storageFraction参数设定,默认是0.5即50%。新的内存管理模型中的优点是,这个边界不是固定的,在内存压力下这个边界是可以移动的。如一个区域内存不够用时可以从另一区域借用内存。下边来讨论如何移动及使用的:

  1.Storage Memory.这部分内存即可以用来缓存spark数据也可以用来做unroll序列化数据的临时空间。广播变量以block的形式也存储在这里。你奇怪的是unroll,因为你可能会说,并不需要那么多空间去unroll block使其可用——在没有足够内存去unroll bolock的情况下,如果得到持久化级别的允许,将直接在这部分内存unroll block。至于广播变量,当它的持久化级别为MEMORY_AND_DISK时,就会缓存到此。

  2.Execution Memory.这部分内存用于存储执行task过程中的一些对象。例如,它可以用来shuflle map端的中间缓存,也可以用来存储hash aggregation过程的hash table.在没有足够内存的时候,这部分内存支持溢室到磁盘,但是这部分内存的blocks不会被其它线程的task挤出去。

 

  下边我们来说一下Storage Memory 和Execution Memory之间的边界移动。从Execution Memory的本质来看,你不能将这部分内存空间的数据挤出去,因为这部分内存的数据是用来计算的中间结果,如果计算过程找不到原来存到这的block数据任务就会失败。但是对于Storage Memory内存就不会这样,它只是用来缓存内存中数据,如果将里边的block数据驱逐出去,就会更新block 元数据映射信息使用到时告知该block被移除了,要想再拿到这些数据从HDD中读取即可(或者如果缓存级别没有溢写就重新计算)。

  所以,我们只能Execution Memory可以向Storage Memory挤用空间,反之不可。那么当什么时候会发生Execution Memory 向Storage Memory挤用空间呢?有两种可能:

  • 只要Storage Memory有可用空间,就可以增大Execution Memory 大小,减少Storage Memory 大小。
  • Storage Memory的空间大小已经超出了初始设定的大小,并且将这部分空间全部占用,在这种情况下就可以强制将从Storage Memory中移出Blocks,减少它的空间到初始大小。

  反过来,在只有当Execution Memory空间有空余时,Storage Memory才可以向Execution Memory借用空间,也就是说Execution Memory只要不够用了就可以向Storage Memory挤占空间不管Storage Memory有没有空余,而Storage Memory只能当Execution Memory有空余时才要以借用不能抢占。

  初始Storage Memory 大小:“Spark Memory” * spark.memory.storageFraction = (“Java Heap” – “Reserved Memory”) * spark.memory.fraction * spark.memory.storageFraction。根据默认值,即(“Java Heap” – 300MB) * 0.75 * 0.5 = (“Java Heap” – 300MB) * 0.375. 如果Java Heap=4G,那么就有1423.5MB大小的Storage Memory空间。

  这就意味着当我们使用Spark cacheu并加载全部数据到executor中时,至少要将Storage Memory大小等于默认初始值大小。因为当Storage Memory区域还没满时,Execution Memory区域已经膨胀大于其初始设定大小时,我们不能强制将Execution Memory抢占的空间数据驱逐,所以最终Storage Memory会变小。

  希望这篇文章可以帮你更好的理解spark新的内存管理机制,并以此来应用。

 

spark1.6内存管理的更多相关文章

  1. Spark(二): 内存管理

    Spark 作为一个以擅长内存计算为优势的计算引擎,内存管理方案是其非常重要的模块: Spark的内存可以大体归为两类:execution和storage,前者包括shuffles.joins.sor ...

  2. Spark 1.6以后的内存管理机制

     Spark 内部管理机制 Spark的内存管理自从1.6开始改变.老的内存管理实现自自staticMemoryManager类,然而现在它被称之为"legacy". " ...

  3. Spark内存管理-UnifiedMemoryManager和StaticMemoryManager

    在Spark-1.6.0中,引入了一个新的参数spark.memory.userLegacyMode(默认值为false),表示不使用Spark-1.6.0之前的内存管理机制,而是使用1.6.0中引入 ...

  4. 【Spark-core学习之八】 SparkShuffle & Spark内存管理

    [Spark-core学习之八] SparkShuffle & Spark内存管理环境 虚拟机:VMware 10 Linux版本:CentOS-6.5-x86_64 客户端:Xshell4 ...

  5. Spark 静态内存管理

    作者编辑:杜晓蝶,王玮,任泽 Spark 静态内存管理详解 一. 内容简介 spark从1.6开始引入了动态内存管理模式,即执行内存和存储内存之间可以互相抢占.spark提供两种内存分配模式,即:静态 ...

  6. Spark(四十六):Spark 内存管理之—OFF_HEAP

    存储级别简介 Spark中RDD提供了多种存储级别,除去使用内存,磁盘等,还有一种是OFF_HEAP,称之为 使用JVM堆外内存 https://github.com/apache/spark/blo ...

  7. Spark 内存管理

    Spark 内存管理 Spark 执行应用程序时, 会启动 Driver 和 Executor 两种 JVM 进程 Driver 负责创建 SparkContext 上下文, 提交任务, task的分 ...

  8. .NET基础拾遗(1)类型语法基础和内存管理基础

    Index : (1)类型语法.内存管理和垃圾回收基础 (2)面向对象的实现和异常的处理 (3)字符串.集合与流 (4)委托.事件.反射与特性 (5)多线程开发基础 (6)ADO.NET与数据库开发基 ...

  9. PHP扩展-生命周期和内存管理

    1. PHP源码结构 PHP的内核子系统有两个,ZE(Zend Engine)和PHP Core.ZE负责将PHP脚本解析成机器码(也成为token符)后,在进程空间执行这些机器码:ZE还负责内存管理 ...

随机推荐

  1. php 将秒数转换为时间(年、天、小时、分、秒)

    $t=1637544; $d=Sec2Time($t); $d为  0年18天 22小时52分24秒 //将秒数转换为时间(年.天.小时.分.秒) function Sec2Time($time){ ...

  2. Oracle 12C -- 网络性能调优

    1.传输数据压缩 网络性能主要受两方面影响:bandwidth和data volume. 在网络层对数据进行压缩,可以减少对网络带宽的需求.而且对应用是透明的. 如果是CPU是瓶颈时开启网络层数据压缩 ...

  3. [Warning] TIMESTAMP with implicit DEFAULT value is deprecated

    启动mysql时,报如下警告信息: [Warning] TIMESTAMP with implicit DEFAULT value is deprecated. Please use --explic ...

  4. openkm预览功能报错:flexpaper License key not accepted(no key passed to viewer)

    openkm:6.3.4 使用google浏览器打开,想预览文件,但是pdf.word和图片都不能显示.只是显示空白. 换成IE后,再次尝试,发现了报错信息: 解决方案: 1- Stop openkm ...

  5. STM8串口初始化寄存器配置

    //库函数配置 UART1_DeInit(); UART1_Init((u32)1000000, UART1_WORDLENGTH_8D, UART1_STOPBITS_1, \ UART1_PARI ...

  6. MySQL与Oracle之间互相拷贝数据的Java程序

    因为工作需要,先是需要将一个小型的MySQL数据库中的数据拷贝到Oracle中:近期又有需要将一个中型的Oracle数据库拷贝到MySQL中.曾经找过网上各种转换工具,大多收费的,自己写个吧,还一切可 ...

  7. Android应用的基本原理

    原文:http://android.eoe.cn/topic/android_sdk 应用基础-Application Fundamentals Android应用程序以java作为开发语言.用And ...

  8. Javascript的&&和||的另类用法

    Javascript的&&和||的另类用法. 又开始研究起 Titanium 来,发现其官方出品的MVC框架(Alloy)还是挺不错的,刚开始苦于没有好的代码来学习,文档又少,所以一直 ...

  9. webstorm的快捷键和zencoding

    1.webstorm快捷键: 生成viewport, meta:vp IntelliJ-Idea 的快捷键 Ctrl+/ 或 Ctrl+Shift+/ 注释(// 或者/*…*/ ) Shift+F6 ...

  10. javascript基础拾遗(一)

    1.判断变量类型 var num = '123'; if(typeof num == 'number'){ alert('this is a number'); } else{ throw 'this ...