我正在构建一个Spark应用程序,我必须缓存大约15 GB的CSV文件。我在这里阅读了Spark 1.6中引入的新UnifiedMemoryManager
:
https://0x0fff.com/spark-memory-management/
作者在User Memory
和Spark 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());
答案 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。由于缺少执行内存,应用程序不会崩溃很重要。如果你不缓存对象,那么最多应用程序将会变慢但不会崩溃。 如果需要更多内存,请为执行程序分配更多内存。