Apache Spark:用户内存与Spark内存

时间:2017-05-03 09:46:25

标签: caching apache-spark memory memory-management rdd

我正在构建一个Spark应用程序,我必须缓存大约15 GB的CSV文件。我在这里阅读了Spark 1.6中引入的新UnifiedMemoryManager

https://0x0fff.com/spark-memory-management/

它也显示了这张图片: enter image description here

作者在User MemorySpark Memory之间有所不同(再次将其分为Storage and Execution Memory)。正如我所说,Spark Memory可以灵活地执行(shuffle,sort等)和存储(缓存)东西 - 如果需要更多内存,它可以从其他部分使用它(如果还没有完全使用)。这个假设是否正确?

用户记忆的描述如下:

  

用户记忆。这是分配Spark Memory后剩余的内存池,完全取决于您喜欢的方式使用它。您可以在那里存储将在RDD转换中使用的数据结构。例如,您可以通过使用mapPartitions转换维护哈希表来重写Spark聚合,以便运行此聚合,这将消耗所谓的用户内存。 [...]再一次,这是用户存储器,它完全取决于你将存储在这个RAM中的内容以及如何,Spark完全没有考虑你在那里做什么以及你是否尊重这个边界。不遵守代码中的此边界可能会导致OOM错误。

如何访问内存的这一部分或如何由Spark管理?

为了我的目的,我只需要有足够的存储空间(因为我不做洗牌,加入等事情)?那么,我可以将spark.memory.storageFraction属性设置为1.0吗?

对我来说最重要的问题是,用户记忆怎么样?为什么它,特别是我上面描述的目的?

当我改变程序以使用某些自己的类时,使用内存是否有区别,例如RDD<MyOwnRepresentationClass>代替RDD<String>

这是我的代码片段(在基准测试应用程序中从Livy Client多次调用它。我正在使用Spark 1.6.2和Kryo​​序列化。

JavaRDD<String> inputRDD = sc.textFile(inputFile);

// Filter out invalid values
JavaRDD<String> cachedRDD = inputRDD.filter(new Function<String, Boolean>() {
    @Override
    public Boolean call(String row) throws Exception {
        String[] parts = row.split(";");

        // Some filtering stuff

        return hasFailure;
    }
}).persist(StorageLevel.MEMORY_ONLY_SER());

2 个答案:

答案 0 :(得分:0)

统一的内存管理器

1)在HEAP上:对象在JVM堆上分配,并由GC绑定。

2)OFF HEAP:对象通过序列化在JVM外部的内存中分配,由应用程序管理,并且不受GC绑定。这种内存管理方法可以避免频繁发生GC,但缺点是必须编写内存分配和内存释放的逻辑。

在堆上:

存储内存:主要用于存储Spark缓存数据,如RDD缓存,广播变量,展开数据等。

执行内存/随机播放内存:主要用于在随机播放,联接,排序,聚合等计算过程中存储临时数据。

用户内存:主要用于存储RDD转换操作所需的数据,例如RDD依赖项的信息。

保留的内存:内存是为系统保留的,用于存储Spark的内部对象。

离线内存:-      1)储存记忆体(随机播放记忆体)      2)执行记忆

答案 1 :(得分:-1)

这是官方文档,我不确定博客中的陈述是否100%准确。 https://spark.apache.org/docs/latest/tuning.html#memory-management-overview

&#34;用户记忆&#34;实际上被称为&#34;执行记忆&#34;。顾名思义它用于 - 在随机,连接,排序和聚合等计算中。当你的代码被执行时,它会使用这个内存并在完成后释放它。试想一下JVM的堆空间用于运行Java程序。当我们的程序运行时,我们隐式使用这个内存。示例 - 将文件读入数据集时,它使用此内存。

&#34;存储内存&#34;当我们使用dataset.cache或dataset.persist调用显式缓存数据集时使用。当我们在代码中显式地取消缓存高速缓存时,将释放此内存。

不建议将spark.memory.storageFraction设置为1.将其保留为默认值0.5。由于缺少执行内存,应用程序不会崩溃很重要。如果你不缓存对象,那么最多应用程序将会变慢但不会崩溃。 如果需要更多内存,请为执行程序分配更多内存。