Spark内存模型初探(2)-User Memory

在上一篇文章Spark内存模型初探(1)-Storage/Execution Memory的使用中,我们初步解析了一下Storage/Execution Memory的使用。最后我们也留下了几个问题,等待我们解答。这些问题更多的集中在User Memory上。

而这段时间,经过思索,探索,以及重新阅读Spark Memory Management,终于解决了大部分。

但是,本文其实更多的是作者的猜测,以及配合Spark Memory Management进行验证。并没有一个非常严谨,科学的方法来验证本文的全部猜测。所以希望读者在读本文的时候,保持怀疑的目光。

UserMemory是怎样被使用的?当我们在RDD.map(function)中的function中初始化新的对象时,是在哪部分内存被初始化的?是不是就是UserMemory?

这个问题的答案,其实在原文里就已经有了。但是由于当时读那篇文章的时候,对Spark内存并不了解,所以这里并没有读懂。

原文中有这么一段:

This is the memory pool that remains after the allocation of Spark Memory, and it is completely up to you to use it in a way you like. You can store your own data structures there that would be used in RDD transformations. For example, you can rewrite Spark aggregation by using mapPartitions transformation maintaining hash table for this aggregation to run, which would consume so called User Memory

要说验证么,我实在是没想出来办法验证。因为从Spark代码中,看不到任何跟User Memory相关的内容。而我们知道,Spark内存分为三部分:Reserved Memory, User Memory, Spark Memory(Storage/Execution Memory)。我们在上篇文章也测试了,function中初始化新的对象时,是不会在Spark Memory中分配的,更不会在Reserved Memory,所以可能的地方就只有在User Memory了。

如果我在function里就是要初始化很多个对象,超过了这个User Memory的大小的话,Spark会怎样做?

先看原文:

its completely up to you what would be stored in this RAM and how, Spark makes completely no accounting on what you do there and whether you respect this boundary or not. Not respecting this boundary in your code might cause OOM error.

我简单写了一点测试代码,来测试这个问题:

package com.hypers.spark

import org.apache.spark.{SparkConf, SparkContext}


/**
  *
  * Reading:
  * Task max available memory is executor heap.
  * 
  * And this program will cause OOM because:
  *     User Memory just 200M, but we allocate an Array[Byte] whose size is 500MB
  *
  **/
object TestTaskAvailableMemory {

    def main(args: Array[String]): Unit = {
        val sparkConf = new SparkConf()
            .setMaster("spark://localhost:7077")
            .setAppName("TestSparkCanRun")

        val sparkContext = new SparkContext(sparkConf)

        val rdd = sparkContext.parallelize(Seq(1))

        rdd.map {
            item => {
                val line = Array.fill[Byte](489354548)(0)
                (item, line)
            }
        }.repartition(1).foreach(println(_))

    }

}

这是会导致OOM的。原因在代码的注释里已经写了。

另外,超过User Memory并不一定会导致OOM。现在User Memory的大小大概是200MB左右,我分配一个300MB的Array[Byte],是没问题的。

我使用的JVM参数是-Xmx1g -XX:+UseSerialGC -XX:-UseAdaptiveSizePolicy -XX:PretenureSizeThreshold=10000000。可以看到,超过10M的对象,就要直接在老年代分配了。可我测试时,老年代的大小是600MB左右。已用100MB。所以这个老年代没有足够的空间来进行分配。所以会出现OOM。

为什么不直接在新生代测试呢?因为新生代的大小共有300MB左右,Eden:Survivor1:Survivor2=240MB:30MB:30MB。而我们的User Memory就已经200MB+了,达不到测试的目的。

从这儿我们也能看到,其实Spark中,Storage/Execution Memory的大小,不会被User Memory挤压。从Spark的源代码中,我们就能看到,它只是一个数字,是MemoryManager(具体类是UnifiedUserMemory或者StaticUserMemory)初始化时就提供的,它并不会在运行时动态获取Java Heap的可用内存大小,进而自动伸缩。

另外,Storage/Exeuction Memory也不是说,你Java Heap在我Spark启动的时候,就给我把Storage/Execution Memory这些内存分配好了,只有我能用,其它人不能用。它只是申明,我需要多少Storage/Execution Memory,你User Memory要是用多了,我Storage/Execution Memory到时候用的时候,你要是给我腾不出来,那咱俩同归于尽。

Shuffle时,Reducer端接收到的数据,是在哪个部分分配的?是不是就是UserMemory?

我认为是在User Memory分配的。但是由于Shuffle是ExternalShuffle,所以并不会占用过多的内存,导致User Memory过大出现OOM。

Spark的内存模型,跟Java内存模型之间,是什么关系?

假设我们的User Memory是300MB,而新生代是200MB,并且没有启用超过阈值就自动在老年代进行分配的机制。

那我们如果在User Memory中分配一个250MB的对象,在这种情况下,新生代根本就放不下这个对象,所以即使我们看到User Memory有300MB可用,实际上也不能分配超过200MB的大对象。

其它的Storage/Execution Memory,跟这个道理类似。

疑问

我们可以看到,由于Java内存模型的缘故,我们可能无形之间碰到一些莫名其妙的坑。

而Spark又支持off-heap Memory,以及Tungsten,那使用这些又如何呢?有什么优缺点呢?

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,088评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,715评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,361评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,099评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,987评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,063评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,486评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,175评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,440评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,518评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,305评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,190评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,550评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,152评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,451评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,637评论 2 335

推荐阅读更多精彩内容