`rdd.map(x => f(g(x))`的性能是否比`rdd.map(g).map(f)`更好?

时间:2015-08-18 02:00:58

标签: performance scala apache-spark

在spark中,我们有两种操作RDD的方法。

一个是让它尽可能短:

rdd.map(x => h(f(g(x))))

另一个是链,使其更具可读性,如:

rdd.map(g).map(f).map(h)...

我个人喜欢后者,这更清楚。但有些人担心性能,他们认为它与:

相同
list.map(g).map(f).map(h)

并且认为在链中会有一些直接的临时RDD,所以他们总是使用前者。

这是真的吗?使用链条有任何性能问题吗?我个人认为它像Stream,我不认为这两者有很大的性能差异

1 个答案:

答案 0 :(得分:3)

这些与流水线代码几乎完全相同。

第一个显而易见的是,当你看起来很清楚时会发生什么,但链接将导致以下(简化):

MapPartitionsRDD(
  MapPartitionsRDD(
    MapPartitionsRDD(
      rdd, 
      iter.map(g)), 
    iter.map(f)),
  iter.map(h))

进一步简化可视化:

map(map(map(rdd,g),f),h)

执行时归结为:

h(f(g(rddItem)))
好像很熟悉?它只是一系列流水线计算......通过懒惰评估的乐趣带给你。

您可以通过示例看到这一点:

def f(x: Int) = {println(s"f$x");x}
def g(x: Int) = {println(s"g$x");x}
def h(x: Int) = {println(s"h$x");x}

val rdd = sc.makeRDD(1 to 3, 1)

rdd.map(x => h(f(g(x))))
g1
f1
h1
g2
f2
h2
g3
f3
h3

rdd.map(g).map(f).map(h)
g1
f1
h1
g2
f2
h2
g3
f3
h3