Apache spark 为什么spark shell中的行计数作业比mapreduce作业运行得慢

Apache spark 为什么spark shell中的行计数作业比mapreduce作业运行得慢,apache-spark,Apache Spark,我做了一个测试来比较spark和mapreduce之间的性能。我有三个节点集群,每个节点都有128GB内存 我运行一个作业来计算10GB文件中的行数 我使用默认的hadoop配置使用mapreduce运行行计数作业。我只需要23秒 当我在spark shell中运行每节点8GB内存的行计数作业时,它花费了我6分钟多的时间,这让我非常惊讶 以下是启动spark shell的命令和spark作业的代码 spark-shell --master spark://10.8.12.16:7077 --e

我做了一个测试来比较spark和mapreduce之间的性能。我有三个节点集群,每个节点都有128GB内存

我运行一个作业来计算10GB文件中的行数

我使用默认的hadoop配置使用mapreduce运行行计数作业。我只需要23秒

当我在spark shell中运行每节点8GB内存的行计数作业时,它花费了我6分钟多的时间,这让我非常惊讶

以下是启动spark shell的命令和spark作业的代码

spark-shell --master  spark://10.8.12.16:7077 --executor-memory 8G
val s= sc.textFile("hdfs://ns/alluxio/linecount/10G.txt")
s.count()
下面是我的spark配置文件:

spark-env.sh

export JAVA_HOME=/home/appadmin/jdk1.8.0_77
export SPARK_HOME=/home/appadmin/spark-2.0.0-bin-without-hadoop
export HADOOP_HOME=/home/appadmin/hadoop-2.7.2
export SPARK_DIST_CLASSPATH=$(/home/appadmin/hadoop-2.7.2/bin/hadoop classpath)
export YARN_CONF_DIR=$HADOOP_HOME/etc/hadoop
export SPARK_LIBARY_PATH=.:$JAVA_HOME/lib:$JAVA_HOME/jre/lib:$HADOOP_HOME/lib/native
export HADOOP_CONF_DIR=$HADOOP_HOME/etc/hadoop
SPARK_MASTER_HOST=10.8.12.16
SPARK_MASTER_WEBUI_PORT=28686
SPARK_LOCAL_DIRS=/home/appadmin/spark-2.0.0-bin-without-hadoop/sparkdata/local
SPARK_WORKER_MEMORY=10g


SPARK_WORKER_DIR=/home/appadmin/spark-2.0.0-bin-without-hadoop/sparkdata/work
SPARK_LOG_DIR=/home/appadmin/spark-2.0.0-bin-without-hadoop/logs
spark-default.conf

spark.driver.memory              5g
spark.eventLog.dir      hdfs://10.8.12.16:9000/spark-event-log

默认情况下,Spark由一个执行器运行。我会将我的设置更改为:

在每台机器上留出8GB用于操作系统和其他进程开销。这将给您留下120GB的空间。如果垃圾收集器的容量超过32GB,垃圾收集器就会开始降级,那么每台机器将有4个执行器,每个执行器的容量为30GB

因此,我将设置:

  • spark.executor.instances
    =12
  • spark.executor.cores
    =(您的每台机器的核心数为-1)/4(留给操作系统1个)
  • spark.executor.memory
    =30g

然后再次运行应用程序

您可以传递分区数,即defaultMinPartitions 调整分区数

像这样

sc.textFile(file, numPartitions)
  .count()  
您也可以在加载后尝试
重新分区
,以查看效果。 还有,看看

您可以通过打印进一步调试和调整设置

sc.getConf.getAll.mkString("\n")
还可以获得执行器的数量,如下面的示例代码段所示

/** Method that just returns the current active/registered executors
        * excluding the driver.
        * @param sc The spark context to retrieve registered executors.
        * @return a list of executors each in the form of host:port.
        */
       def currentActiveExecutors(sc: SparkContext): Seq[String] = {
         val allExecutors = sc.getExecutorMemoryStatus.map(_._1)
         val driverHost: String = sc.getConf.get("spark.driver.host")
         allExecutors.filter(! _.split(":")(0).equals(driverHost)).toList
       }

sc.getConf.getInt("spark.executor.instances", 1)

getExecutorStorageStatus
getExecutorMemoryStatus
都返回包括驱动程序在内的执行器数量。

它确实有效。但是spark的工作仍然花费了我超过1分钟的时间。spark作业仍然比MR低很多。当我使用命令“s.count()”运行spark作业时,在“[Stage 2:>(0+80)/80]”中卡住大约需要1分钟。当进度条移动时,大约需要20秒才能完成。为什么会这样?我听从了你的建议,结果稍微好一点。spark作业需要1分钟才能完成。但是,我的mapreduce作业只需要23秒。mapreduce作业是否将数据保留在操作系统缓存中,从而使其性能优于spark作业?spark作业可能不使用缓存中的数据。有可能吗?更新了我的答案。您需要调试更多的代码,我已经完成了mapreduce和spark,它们都是生产级代码。但我的观察结果是,如果我们不能正确调整参数,spark的速度会很慢。我们觉得mapreduce在速度方面更好。通过多种方式查看spark中的性能调整。我们能够看到速度的急剧变化。最后,我们能够证明spark代码对于相同的逻辑运行得更快。。请通过更深入地了解参数来进一步微调参数。:-)微调中的任何其他发现。你能解决吗?谢谢。现在我知道了为什么spark作业比mapreduce运行得慢的关键点。Tunning很重要。我将采取一些工作来调整我的火花工作与您提到的文件。