Performance Spark Dataframe本机性能与简单字符串拆分操作上的Pyspark RDD映射

Performance Spark Dataframe本机性能与简单字符串拆分操作上的Pyspark RDD映射,performance,apache-spark,pyspark,apache-spark-sql,spark-dataframe,Performance,Apache Spark,Pyspark,Apache Spark Sql,Spark Dataframe,我不希望下面的代码从Dataframe Catalyst查询优化器中受益,但我确实希望string split的Scala/本机性能与Python性能之间存在性能差异。但是,我的性能结果令人失望,因为本机Dataframe API似乎速度较慢 我的测试如下: def get_df(spark): return spark.read.load('s3://BUCKET/test-data.csv', format='com.databr

我不希望下面的代码从Dataframe Catalyst查询优化器中受益,但我确实希望string split的Scala/本机性能与Python性能之间存在性能差异。但是,我的性能结果令人失望,因为本机Dataframe API似乎速度较慢

我的测试如下:

def get_df(spark):
    return spark.read.load('s3://BUCKET/test-data.csv',
                           format='com.databricks.spark.csv',
                           inferSchema='true', header='true')

def upsize_df(df, exponent=10):
    for i in range(exponent):
        df = df.unionAll(df)
    return df

def rdd_ver(df):
    df = df.rdd.map(lambda row: row + tuple(
                        row.order_id.split('-'))).toDF(
                            df.columns + ['psrid', 'eoid'])
    df.show()

def df_ver(df):
    split_col = pyspark.sql.functions.split(df['order_id'], '-')
    df = df.withColumn('psrid', split_col.getItem(0))
    df = df.withColumn('eoid', split_col.getItem(1))
    df.show()
簇/纱线详细信息:

  • AWS上的Spark 2.0
  • 6遗嘱执行人
  • 每个执行器2个内核
试验程序:

  • 在IPython中创建新的PySpark外壳
  • 获取玩具大小数据集的数据帧(1000行)
  • 将数据帧重新分区为12个分区
  • 使用
    unionAll
    将_df
    放大,以达到100万行
  • 运行
    df.count()
  • 最后,运行
    %time-rdd\u-ver(df)
    %time-df\u-ver(df)
到目前为止,我的结果令人惊讶和失望。以下是我收到的结果样本,以秒为单位:

rdd版本
:14.5,22.4,13.1,24.7,17.8---
平均值:18.5

df\u ver
:30.5,26.9,32.0,29.7,39.8---
平均值:31.8

我希望您能对测试过程本身(操作本身源自某些生产代码)或Dataframe版本的糟糕性能有任何想法

编辑:

Spark Web UI表明我的作业实际上没有很快地安排/提交。我不确定Web UI的信息有多可靠,但此屏幕截图中活动工单上显示的“提交”时间在我在活动Pyspark会话中首次点击“回车”以启动
%time df\u ver(df)

此外,6名遗嘱执行人似乎都没有做任何事情。他们显然都是被Spark杀死的,因为我在Spark会话中没有积极地做任何事情超过几秒钟。看起来整个作业都是由驱动程序节点运行的,但我无法确认这一点,因为我对Spark Web UI了解不够


为什么您认为scala的速度应该更快?Python字符串操作非常快:

蟒蛇: 斯卡拉:
你为什么认为scala的速度应该更快?Python字符串操作非常快:

蟒蛇: 斯卡拉:
我将
df.explain(extended=true)
查看计划。另外,看看web UI的SQL选项卡,深入到作业/任务和其他指标。墙上的时钟数字似乎与Spark web UI给我的非常不同。然而,Spark Web UI的数字很难解释。我给这个问题附上了一个屏幕截图。我想
df.explain(extended=true)
看看计划。另外,看看web UI的SQL选项卡,深入到作业/任务和其他指标。墙上的时钟数字似乎与Spark web UI给我的非常不同。然而,Spark Web UI的数字很难解释。我给这个问题附上了一个截图。在我看来,这不是一个非常可靠的基准。我希望Scala能够更快地执行大量操作,因为它在JVM上运行编译的字节码,而不是解释的代码。此外,使用DataFrameAPI应该需要更少的上下文切换,因为不需要在工作节点上调用Python解释器。即使Python和Scala一样快(通常不是),我也希望DataFrameAPI和Python RDD映射一样快。我没有注意到这一点,因此我的问题是,瓶颈不会是启动python解释器。无论如何,我的观点是python中的字符串处理实际上比scala中的要快,这可以解释您的计时。请看一看更深入的探索。在我看来,这不是一个非常健壮的基准测试。我希望Scala能够更快地执行大量操作,因为它在JVM上运行编译的字节码,而不是解释的代码。此外,使用DataFrameAPI应该需要更少的上下文切换,因为不需要在工作节点上调用Python解释器。即使Python和Scala一样快(通常不是),我也希望DataFrameAPI和Python RDD映射一样快。我没有注意到这一点,因此我的问题是,瓶颈不会是启动python解释器。无论如何,我的观点是python中的字符串处理实际上比scala中的要快,这可以解释您的计时
In [58]: %time "this is my string".split()
CPU times: user 5 µs, sys: 1 µs, total: 6 µs
Wall time: 7.87 µs
bash-3.2$ echo '
object TimeSplit {
   def main(args: Array[String]): Unit = {
     val now = System.nanoTime
     val split = "this is my string".split(" ")
     val diff = System.nanoTime - now
     println("%d microseconds".format(diff/1000))
   }
 }' > timesplit.scala

bash-3.2$ scalac timesplit.scala
bash-3.2$ scala TimeSplit
21 microseconds