在sc.runJob
调用dagScheduler.runJob
之前,在{rdd'上执行的func由ClosureCleaner.clean
“清除”。
为什么火花必须这样做?目的是什么?
答案 0 :(得分:13)
当Scala构造一个闭包时,它确定闭包将使用哪些外部变量,并在闭包对象中存储对它们的引用。这允许闭包即使从与其创建的范围不同的范围调用它也能正常工作。
Scala有时会在捕获太多外部变量时出错(参见SI-1419)。在大多数情况下,这是无害的,因为额外捕获的变量根本不会被使用(尽管这会阻止它们获得GC)。但它给Spark带来了一个问题,它必须通过网络发送闭包,以便它们可以在奴隶上运行。当一个闭包包含不必要的引用时,它会浪费网络带宽。更重要的是,一些引用可能指向不可序列化的对象,而Spark将无法序列化闭包。
要在Scala中解决此错误,ClosureCleaner会在运行时遍历对象并修剪不必要的引用。由于它在运行时执行此操作,因此它可以比Scala编译器更准确。然后Spark可以安全地序列化已清理的闭包。