Apache spark 为什么spark shell中的行计数作业比mapreduce作业运行得慢
我做了一个测试来比较spark和mapreduce之间的性能。我有三个节点集群,每个节点都有128GB内存 我运行一个作业来计算10GB文件中的行数 我使用默认的hadoop配置使用mapreduce运行行计数作业。我只需要23秒 当我在spark shell中运行每节点8GB内存的行计数作业时,它花费了我6分钟多的时间,这让我非常惊讶 以下是启动spark shell的命令和spark作业的代码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-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 因此,我将设置:
=12spark.executor.instances
=(您的每台机器的核心数为-1)/4(留给操作系统1个)spark.executor.cores
=30gspark.executor.memory
然后再次运行应用程序 您可以传递分区数,即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很重要。我将采取一些工作来调整我的火花工作与您提到的文件。