Mar*_*icz 7 java performance jvm scala apache-spark
不同的来源(例如1和 2)声称Spark可以从同一JVM中运行多个任务中受益.但他们没有解释原因.
这些好处是什么?
最大的优点是共享内存,特别是处理广播对象。因为这些对象被认为是只读的,所以可以在多个线程之间共享。
在使用单个任务/执行器的情况下,每个 JVM 都需要一个副本,因此如果有 N 个任务,则有 N 个副本。对于大型对象,这可能是一个严重的开销。
相同的逻辑可以应用于其他共享对象。
正如已经说过的广播变量是一回事。
另一个是并发问题。看看这段代码:
var counter = 0
var rdd = sc.parallelize(data)
rdd.foreach(x => counter += x)
println(counter)
Run Code Online (Sandbox Code Playgroud)
结果可能会有所不同,具体取决于是在本地执行还是在部署在集群上的 Spark(具有不同的 JVM)上执行。在后一种情况下,该parallelize方法在执行器之间拆分计算。计算闭包(每个节点执行其任务所需的环境),这意味着每个执行器都会收到counter. 每个 executor 看到自己的变量副本,因此计算结果为 0,因为没有一个 executor 引用了正确的对象。另一方面,在一个 JVM 中counter,每个工作人员都可以看到。
当然,有一种方法可以避免这种情况 - 使用Acumulators(请参阅此处)。
最后但并非最不重要的是,当将RDDs持久化到内存中时(默认cache方法存储级别为MEMORY_ONLY),它将在单个 JVM 中可见。这也可以通过使用来克服OFF_HEAP(这是 2.4.0 中的实验)。更多在这里。