用.unpersist()手动管理内存是个好主意吗?

时间:2017-11-16 14:01:13

标签: scala apache-spark garbage-collection spark-dataframe

我在这里读了很多关于数据帧的unpersist()的问题和答案。到目前为止,我还没有找到这个问题的答案:

在Spark中,一旦我完成了数据帧,最好调用.unpersist()来手动强制该数据帧从内存中取消,而不是等待GC(这是一个昂贵的任务)?在我的情况下,我正在加载许多数据帧,以便我可以执行连接和其他转换。

因此,例如,如果我希望加载和连接3个数据帧A,B和C: 我加载数据帧A和B,加入这两个来创建X,然后加入.unpersist()B因为我不再需要它(但我需要A),并且可以使用内存来加载C(这很大) )。然后我加载C,并在C上将C加到X,.unpersist(),这样我就可以在X和A上执行的操作有更多的内存。

我知道GC最终会为我解决,但我也明白,GC是一项昂贵的任务,如果可能的话应该避免。重新说出我的问题:这是一种手动管理内存的合适方法,以优化我的火花作业吗?

我的理解(如果错误,请更正):

  • 我明白.unpersist()是一种非常便宜的操作。
  • 我知道GC最终会在我的数据帧上调用.unpersist()。
  • 我了解spark会根据“最近使用的”策略监控缓存和丢弃。但在某些情况下我不希望删除'Last Used'DF,所以我可以在数据文件上调用.unpersist()我知道我将需要在将来,我不会删除我 需要的DF,并且必须在以后重新加载它们。

如果不清楚,再次重新提出我的问题:这是否适合使用.unpersist(),或者我应该让Spark和GC完成他们的工作?

提前致谢:)

1 个答案:

答案 0 :(得分:2)

似乎有一些误解。虽然使用unpersist是一种有效的方法来更好地控制存储,但它并不能避免垃圾收集。事实上,与缓存数据相关联的所有on heap对象都将被留下垃圾收集器。

因此,虽然操作本身相对便宜,但它触发的事件链可能并不便宜。幸运的是,明确的持久性并不比等待自动清洁器或GC触发的清洁器差,所以如果你想清理特定的物体,请继续操作。

要限制GC对unpersist的限制,可能需要查看OFF_HEAP StorageLevel