【问题标题】:Spark applicaition - Java.lang.OutOfMemoryError: Java heap spaceSpark 应用程序 - Java.lang.OutOfMemoryError:Java 堆空间
【发布时间】:2016-03-02 01:11:18
【问题描述】:

我用的是Spark Standalone单机,内存128G,32核。以下是我认为与我的问题相关的设置:

spark.storage.memoryFraction     0.35
spark.default.parallelism        50
spark.sql.shuffle.partitions     50

我有一个 Spark 应用程序,其中有 1000 个设备的循环。对于每个循环(设备),它准备特征向量,然后调用 MLLib 的 k-Means。在循环第 25 到第 30 次迭代(处理第 25 到第 30 个设备)时,遇到“Java.lang.OutOfMemoryError: Java heap space”的错误。

我尝试了从 0.7 到 0.35 的 memoryFraction,但没有帮助。我还尝试了 200 的并行/分区,但没有运气。 JVM 选项是“-Xms25G -Xmx25G -XX:MaxPermSize=512m”。我的数据大小只有2G左右。

这是堆栈跟踪:

java.lang.OutOfMemoryError: Java heap space
  at java.util.Arrays.copyOf(Arrays.java:2271)
  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.write(ObjectOutputStream.java:1841)
  at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1533)
  at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1508)
  at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1431)
  at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1177)
  at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:347)
  at scala.collection.mutable.HashMap$$anonfun$writeObject$1.apply(HashMap.scala:138)
  at scala.collection.mutable.HashMap$$anonfun$writeObject$1.apply(HashMap.scala:136)
  at scala.collection.mutable.HashTable$class.foreachEntry(HashTable.scala:230)
  at scala.collection.mutable.HashMap.foreachEntry(HashMap.scala:40)
  at scala.collection.mutable.HashTable$class.serializeTo(HashTable.scala:125)
  at scala.collection.mutable.HashMap.serializeTo(HashMap.scala:40)
  at scala.collection.mutable.HashMap.writeObject(HashMap.scala:136)
  at sun.reflect.GeneratedMethodAccessor116.invoke(Unknown Source)
  at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
  at java.lang.reflect.Method.invoke(Method.java:606)
  at java.io.ObjectStreamClass.invokeWriteObject(ObjectStreamClass.java:988)
  at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1495)
  at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1431)
  at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1177)
  at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1547)
  at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1508)
  at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1431)
  at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1177)
  at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1547)
  at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1508)
  at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1431)
  at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1177)

应用程序刚开始看起来还不错,但是运行了一段时间,处理的设备越来越多,Java堆逐渐被占用,JVM没有释放内存。如何诊断和解决此类问题?

【问题讨论】:

  • 它正在尝试序列化这样的数据,可能是非常大的数据。我建议您将最大堆大小增加到 100 GB 而不是 25 GB。
  • 现在尝试堆大小 100G。感谢您的建议。
  • 您是否尝试将 spark.rdd.compress 设置为 true?

标签: java apache-spark jvm out-of-memory heap-memory


【解决方案1】:

您始终可以使用像visualVM 这样的分析工具。监控内存增长。 希望您使用的是 64 位 JVM 而不是 32 位 JVM。 32位进程只能使用2GB内存,所以内存设置基本上是没有用的。希望这会有所帮助

【讨论】:

  • 感谢您推荐 visualVM。我现在正在尝试监视内存使用情况。顺便说一句,我使用的是 64 位 JVM。
【解决方案2】:

除了 Driver 和 Executor 内存,建议尝试以下选项:-

  1. 切换到 Kryo 序列化 - http://spark.apache.org/docs/latest/tuning.html#data-serialization
  2. 使用 MEMORY_AND_DISK_SER_2 进行 RDD 持久性。

如果你能把代码贴出来就好了。

【讨论】:

  • 感谢您的建议!我已经使用了 Kryo 序列化。由于 MEMORY_AND_DISK_SER_2 比 MEMORY_ONLY 慢得多,所以除非没有其他选择,否则我不愿意使用它。
  • 我同意,但建议“MEMORY_AND_DISK_SER_2”的目的是首先确保您的工作至少完成。这将验证您的逻辑是否正确但未优化,然后我们可以对其进行调整以获得更好的性能,使其完全在内存中执行。
  • 我会试试 MEMORY_AND_DISK_SER_2 选项。
  • 你可以尝试增加 --memoryOverhead 选项,一般是执行器内存的 20 %,这肯定解决了一些 OOM 问题
【解决方案3】:

JVM 选项不足以配置 Spark 内存,您还需要设置 spark.driver.memory(用于驱动程序,obv。)和spark.executor.memory(用于工作人员)。这些默认设置为 1gb。 See this thorough guide 了解更多信息。实际上,我敦促您阅读它,那里有很多东西,熟悉它肯定会有所收获。

【讨论】:

  • 在我的设置中,我有“spark.driver.memory 16G”和“spark.executor.memory 96G”。我实际上浏览了 Spark 配置文档,但仍然无法解决我的 OOM 问题。我现在正在尝试使用 visualVM 来查看堆中发生的情况。
猜你喜欢
  • 2014-02-04
  • 1970-01-01
  • 2018-12-07
  • 1970-01-01
  • 2015-09-28
  • 1970-01-01
  • 2010-12-08
相关资源
最近更新 更多