jvm 为什么Apache Spark executor在向文件中写入远小于配置内存的内容时会导致OutOfMemoryError?

wvt8vs2t  于 4个月前  发布在  Apache
关注(0)|答案(1)|浏览(53)

我试图诊断由Spark执行器引起的OutOfMemoryError,希望有人能在这里帮助我。

配置

我在我的Windows机器上以本地模式运行Spark(3.1.3)。我的JVM示例设置为2g内存。我的Spark执行器内存为1g(spark.executor.memory)。

场景

我只是对本地文件系统中的一些parquet文件运行了一个Spark SQL查询。我想测试我们系统的其他部分,看看它如何处理一个超长记录(行),所以我给出了一个Spark SQL查询,如下所示:

SELECT repeat('A', 50000000) AS test

字符串
当我运行这个查询并写入一个csv文件时,JVM进程崩溃了,出现java.lang.OutOfMemoryError:Java堆空间

问题

据我所知,输入数据大约是50 MB(5000万个字符),这应该比配置的执行器内存空间(1g)小得多。
我检查了堆转储,确实看到了这个char数组的许多副本,导致大约800 MB的内存使用。
但是,如果我使用一个不同的查询,输入更大(比如200 MB),但不是这么大的行,那就没问题了。
Spark一张唱片拷贝这么多份正常吗?有什么办法可以避免这种OOM吗?谢谢

参考资料

以下是例外的一部分:

Thread 'Executor task launch worker for task 0.0 in stage 6.0 (TID 35)' with ID = 135
java.lang.OutOfMemoryError.<init>(OutOfMemoryError.java:48)
java.util.Arrays.copyOf(Arrays.java:3332)
    com.univocity.parsers.common.input.ExpandingCharAppender.expand(ExpandingCharAppender.java:115)
    com.univocity.parsers.common.input.ExpandingCharAppender.expand(ExpandingCharAppender.java:123)
    com.univocity.parsers.common.input.ExpandingCharAppender.append(ExpandingCharAppender.java:207)
com.univocity.parsers.csv.CsvWriter.append(CsvWriter.java:405)
com.univocity.parsers.csv.CsvWriter.processRow(CsvWriter.java:228)
    com.univocity.parsers.common.AbstractWriter.submitRow(AbstractWriter.java:352)
    com.univocity.parsers.common.AbstractWriter.writeRow(AbstractWriter.java:830)
    org.apache.spark.sql.catalyst.csv.UnivocityGenerator.write(UnivocityGenerator.scala:94)
    org.apache.spark.sql.execution.datasources.csv.CsvOutputWriter.write(CsvOutputWriter.scala:46)
    org.apache.spark.sql.execution.datasources.SingleDirectoryDataWriter.write(FileFormatDataWriter.scala:140)


我试过阅读Spark内存管理,但仍然可以找到相关的材料。我试过缓存数据,并将数据只持久化在磁盘上,但没有任何帮助。

ymzxtsji

ymzxtsji1#

从你的描述中,你似乎是在单JVM模式下运行Spark,这是 * 本地 * 模式,而不是 * 独立 *,这实际上是一个集群运行时。
在本地模式下,不使用执行器设置,您需要使用spark.driver.memory=2g config或--driver-memory 2g spark-submit参数指定驱动程序的内存需求。

相关问题