我编写了一些代码来读取多个镶木地板文件并将其缓存以供后续使用。我的代码看起来像这样简化
val data = SparkStartup.sqlContext.read.parquet(...)
data.setName(...).persist(StorageLevel.MEMORY_AND_DISK_SER).collect()
map += data
镶木地板文件总共大约11克。我通过以下方式配置我的应用程序:
val sparkConfig = new SparkConf().setAppName(...).setMaster("local[128]")
sparkConfig.set("spark.serializer", "org.apache.spark.serializer.KryoSerializer")
sparkConfig.set("spark.kryoserializer.buffer.max", "512m");
sparkConfig.set("spark.kryoserializer.buffer", "256");
sparkConfig.set("spark.driver.maxResultSize", "0");
sparkConfig.set("spark.driver.memory", "9g");
我认为通过使用MEMORY_AND_DISK_SER
,如果使用太多内存,Spark会溢出到磁盘。但是,我得到了`java.lang.OutOfMemoryError:
at java.util.Arrays.copyOf(Arrays.java:3230)
at java.io.ByteArrayOutputStream.grow(ByteArrayOutputStream.java:113)
at java.io.ByteArrayOutputStream.ensureCapacity(ByteArrayOutputStream.java:93)
at java.io.ByteArrayOutputStream.write(ByteArrayOutputStream.java:140)
at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:82)
at java.io.BufferedOutputStream.write(BufferedOutputStream.java:126)
at com.esotericsoftware.kryo.io.Output.flush(Output.java:155)
at com.esotericsoftware.kryo.io.Output.require(Output.java:135)
at com.esotericsoftware.kryo.io.Output.writeAscii_slow(Output.java:446)
at com.esotericsoftware.kryo.io.Output.writeString(Output.java:306)
at com.esotericsoftware.kryo.util.DefaultClassResolver.writeName(DefaultClassResolver.java:105)
at com.esotericsoftware.kryo.util.DefaultClassResolver.writeClass(DefaultClassResolver.java:81)
at com.esotericsoftware.kryo.Kryo.writeClass(Kryo.java:472)
这是为什么?我用-Xmx9g -Dspark.executor.memory=9g -Dspark.executor.cores=3
启动我的应用程序。对于在一切崩溃之前读取的文件,我可以在SparkUI中看到,当读取到内存时,镶木地板文件的大小是其大小的9倍。
答案 0 :(得分:7)
这是因为您在驱动程序应用程序中调用了collect()
。这会返回Array
个数据项,这些数据项需要适合内存。
您应该使用data
RDD并将您的大量数据映射,缩小,分组等转换为所需的结果,然后collect()
该数据量较小的数据。