在 Spark 1.6.0 中调试“检测到托管内存泄漏”

Posted

技术标签:

【中文标题】在 Spark 1.6.0 中调试“检测到托管内存泄漏”【英文标题】:Debugging "Managed memory leak detected" in Spark 1.6.0 【发布时间】:2015-12-18 15:45:03 【问题描述】:

我已尝试升级到 Apache Spark 1.6.0 RC3。我的应用程序现在几乎每项任务都会出现这些错误:

Managed memory leak detected; size = 15735058 bytes, TID = 830

我已将 org.apache.spark.memory.TaskMemoryManager 的日志记录级别设置为 DEBUG 并在日志中查看:

I2015-12-18 16:54:41,125 TaskSetManager: Starting task 0.0 in stage 7.0 (TID 6, localhost, partition 0,NODE_LOCAL, 3026 bytes)
I2015-12-18 16:54:41,125 Executor: Running task 0.0 in stage 7.0 (TID 6)
I2015-12-18 16:54:41,130 ShuffleBlockFetcherIterator: Getting 1 non-empty blocks out of 1 blocks
I2015-12-18 16:54:41,130 ShuffleBlockFetcherIterator: Started 0 remote fetches in 0 ms
D2015-12-18 16:54:41,188 TaskMemoryManager: Task 6 acquire 5.0 MB for null
I2015-12-18 16:54:41,199 ShuffleBlockFetcherIterator: Getting 1 non-empty blocks out of 1 blocks
I2015-12-18 16:54:41,199 ShuffleBlockFetcherIterator: Started 0 remote fetches in 0 ms
D2015-12-18 16:54:41,262 TaskMemoryManager: Task 6 acquire 5.0 MB for null
D2015-12-18 16:54:41,397 TaskMemoryManager: Task 6 release 5.0 MB from null
E2015-12-18 16:54:41,398 Executor: Managed memory leak detected; size = 5245464 bytes, TID = 6

您如何调试这些错误?有没有办法记录分配和解除分配的堆栈跟踪,以便我可以找到哪些泄漏?

我对新的统一内存管理器 (SPARK-10000) 了解不多。泄漏可能是我的错还是可能是 Spark 错误?

【问题讨论】:

您是否尝试使用设置在调试级别的记录器来运行? 谢谢!我现在使用<logger name="org.apache.spark.memory.TaskMemoryManager" level="DEBUG" /> 运行,并记录了分配和解除分配。仍然不知道发生了什么:)。稍后我会添加更多细节。 我已经添加了日志。有两个 5MB acquire 调用和一个 5MB release 调用。但为什么呢? 您在使用数据框吗?在尝试操作数据帧时,我开始出现大量此类错误。内存泄漏似乎与 Java 进程有关,随着应用程序的运行,它会不断地消耗更多的内存。 不,这是没有 DataFrames 的。我不认为这是Java的事情。这由 Spark 的内存管理器记录,其中任务可以显式获取和释放内存。任务结束,但有些东西没有发布。内存管理器会自动释放这个,但会记录这个警告,让我们知道有问题。 【参考方案1】:

简短的回答是用户不应该看到此消息。用户不应该能够在统一内存管理器中创建内存泄漏。

发生此类泄漏是 Spark 错误:SPARK-11293


但如果你想了解内存泄漏的原因,我就是这样做的。

    下载 Spark 源代码并确保您可以构建它并且您的构建工作正常。 在TaskMemoryManager.java 中添加额外的登录acquireExecutionMemoryreleaseExecutionMemory: logger.error("stack trace:", new Exception()); 将所有其他调试日志更改为TaskMemoryManager.java 中的错误。 (比弄清楚日志配置更容易......)

现在您将看到所有分配和解除分配的完整堆栈跟踪。尝试匹配它们并找到没有解除分配的分配。您现在有了泄漏源的堆栈跟踪。

【讨论】:

我在 EMR 16/04/14 13:49:10 上运行 spark 流时看到了这个异常 WARN memory.TaskMemoryManager: leak 32.3 MB memory from org.apache.spark.unsafe.map.BytesToBytesMap@ 34158d5f 16/04/14 13:49:10 错误 executor.Executor:检测到托管内存泄漏;大小 = 33816576 字节,TID = 2942915 16/04/14 13:49:10 错误 executor.Executor:阶段 35684.0 中的任务 22.0 异常(TID 2942915) java.lang.OutOfMemoryError:无法获取 262144 字节的内存,得到 220032 所有这些评论是否意味着,如果由于公司 IT 准备就绪,我还不能升级到“好”版本,我可以放心地忽略错误吗?我目前正在使用 spark 1.6.0 并且当某些数据框先“不同”然后“头”时出现这样的错误。 好吧,如果忽略它是您唯一的选择,我建议您忽略它:)。它可能会导致内存不足问题,即内存错误记帐的警告。 我们在 spark 2.3.1 上看到了它。任何想法为什么? 可能是一个错误!我会提交一个关于它的 JIRA 问题,看看是否有人可以追踪它。【参考方案2】:

我也发现了这个警告信息,但它是由“df.repartition(rePartNum,df("id"))”引起的。 我的 df 是空的,警告消息的行等于 rePartNum。 版本: 火花2.4 win10

【讨论】:

以上是关于在 Spark 1.6.0 中调试“检测到托管内存泄漏”的主要内容,如果未能解决你的问题,请参考以下文章

Spark 1.6.0 DenseMatrix 更新值

SQLContext.sql 上的 Spark NoSuchMethodError(Cloudera 5.8.0 上的 Spark 1.6.0)

Spark Streaming 1.6.0 中 Checkpointing/WAL 的可靠性问题

Spark-1.6.0中的Sort Based Shuffle源码解读

Spark源码学习和总结1

Spark UnifiedMemoryManager和StaticMemoryManager