Spark-需要改进代码以修复OutOfMemoryError:Java堆空间吗?

时间:2018-08-05 09:16:57

标签: scala apache-spark apache-spark-sql out-of-memory

运行Spark作业时出现以下OutOfMemoryError错误。首先,我使用以下配置: --executor-memory 4g --driver-memory 2g --num-executors 1 --executor-cores 2

但是在发生错误之后,我增加了驱动程序的执行程序内存以及执行程序的数量:--executor-memory 8g --driver-memory 8g --num-executors 10 --executor-cores 1

但是它没有帮助,并且再次发生了错误。现在我想知道这是否可能是由于我编写代码的方式引起的吗?我正在处理来自API的约15,000条记录。我怀疑我如何映射salesFromApi并最终应用.toArray可能有问题。我还有其他需要改进的地方,例如重新划分RDD吗?

val processedSales: Array[String] = salesFromApi
.map(store => processor.doSalesProcessing(store.id).toArray

val salesRDD: RDD[String] = sc.parallelize(processedSales)
val salesDf: DataFrame = sqlContext.read.json(salesRDD)
val specialDataDF: DataFrame = salesDf.select(...various fields from salesDf)

val salesColumns: Array[Column] = specialDataDF.columns.map(col)
salesDF.select(concat_ws(",", salesColumns : _*)).write.text(s3Dir)

java.lang.OutOfMemoryError: Java heap space
    at java.util.Arrays.copyOf(Arrays.java:3236)
    at java.io.ByteArrayOutputStream.grow(ByteArrayOutputStream.java:118)
    at java.io.ByteArrayOutputStream.ensureCapacity(ByteArrayOutputStream.java:93)
    at java.io.ByteArrayOutputStream.write(ByteArrayOutputStream.java:153)
    at java.io.ObjectOutputStream$BlockDataOutputStream.drain(ObjectOutputStream.java:1877)
    at java.io.ObjectOutputStream$BlockDataOutputStream.setBlockDataMode(ObjectOutputStream.java:1786)
    at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1189)
    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:348)
    at org.apache.spark.serializer.JavaSerializationStream.writeObject(JavaSerializer.scala:44)
    at org.apache.spark.serializer.JavaSerializerInstance.serialize(JavaSerializer.scala:101)
    at org.apache.spark.scheduler.Task$.serializeWithDependencies(Task.scala:200)
    at org.apache.spark.scheduler.TaskSetManager.resourceOffer(TaskSetManager.scala:460)

2 个答案:

答案 0 :(得分:1)

您可以尝试调用.view而不是.toArray吗? view方法将创建一个SeqView,它是集合的一个懒惰版本。使用.toArray,您整个15k左右的时间都将在该调用中求值。

答案 1 :(得分:1)

这可能无济于事,但是您可以尝试使用以下几种策略来找出问题的根源。祝你好运。

(1)增加您的spark开销值,以便在每个容器中分配更多空间供java用尽。这将有助于找出问题所在的位置,从而将问题隔离到纱线容器中。

--conf "spark.yarn.executor.memoryOverhead=4000m"
--conf "spark.yarn.driver.memoryOverhead=2000m" 

(2)将驱动程序和执行程序的内存分别增加到12,20。这将检查它是否与您的写入有关。

(3)保留输入数据帧。检查JSON的解析是否引起背景开销,如果我们坚持下去,我们将其切掉。还要尝试缓存rdd,我们希望删除尽可能多的开销过程。     salesDF.persist     salesDF.count

(4)如果toArray引起了问题,请尝试将其更改为collect,它还将把post map对象更改为字符串数组。