1 前言
由于未经声明的参数行为变化, 2.3.0的性能对比惨到不行。本轮测试在之前的基础上对2.3.0加上额外的参数设置spark.sql.statistics.fallBackToHdfs true进行新一轮的性能测试,以期望令人满意的结果。
2 测试数据
| benchmark | scale | fileformat | partitioned | link | 
|---|---|---|---|---|
| TPCDS | 1T | parquet | true | https://github.com/yaooqinn/tpcds-for-spark | 
3 实验对象
3.1 参照组
| baseline | modified | commit | link | 
|---|---|---|---|
| 2.1.2 | true | 9ef23ae | https://github.com/yaooqinn/spark/tree/v2.1.2-based | 
3.2 实验组
| baseline | modified | commit | link | 
|---|---|---|---|
| 2.3.0 | false | 992447f | https://github.com/yaooqinn/spark/tree/v2.3.0-based | 
4 配置
4.1 硬件配置
| 机器类别 | CPU | Memory | Disk | 台数 | Services | 
|---|---|---|---|---|---|
| 虚拟机 | 4 × 1 × 1 | 32g | 500g × 1 | 5 | NN(1) SNN (1) RM(1) HMS(1) SHS(1) | 
| 物理机 | 48 × 2 × 12 | 256g | 7.3T × 12 | 3 | DN(3) NM(3) | 
| 物理机 | 48 × 2× 12 | 256g | 1.1T × 1 | 4 | DN(4) NM(4) | 
| 物理机 | 32 × 2 × 8 | 128g | 3.6T × 12 | 1 | DN(1) NM(1) | 
| 物理机 | 40 × 2 × 10 | 256g | 500g × 1 | 1 | NM(1) | 
| 物理机 | 48 × 2 × 12 | 32g | 1.1T × 1 | 1 | DN(1) | 
4.2 metrics

hdfs

yarn
4.3 SparkConf
## Basic Settings ##spark.master yarn spark.submit.deployMode client spark.serializer org.apache.spark.serializer.KryoSerializer spark.kryoserializer.buffer.max 256m spark.local.dir ./local## Hadoop Settings ##spark.hadoop.fs.hdfs.impl.disable.cache truespark.hadoop.fs.file.impl.disable.cache true## Driver/AM Settings ##spark.yarn.am.cores 2 spark.yarn.am.memory 2g spark.yarn.am.memoryOverhead 512 spark.yarn.am.extraJavaOptions -XX:PermSize=1024m -XX:MaxPermSize=2048m -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintTenuringDistribution spark.driver.maxResultSize 2g spark.driver.memory 30g spark.driver.extraJavaOptions -XX:PermSize=1024m -XX:MaxPermSize=1024m## Executor Settings ##spark.executor.instances 40 spark.executor.cores 4 spark.executor.memory 20g spark.executor.memoryOverhead 4096 spark.executor.extraJavaOptions -XX:PermSize=1024m -XX:MaxPermSize=1024m -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintTenuringDistribution## Security Settings ##spark.yarn.keytab ? spark.yarn.principal ?## Dynamic Allocation Settings ##spark.shuffle.service.enabled truespark.dynamicAllocation.enabled falsespark.dynamicAllocation.initialExecutors 1 spark.dynamicAllocation.minExecutors 1 spark.dynamicAllocation.maxExecutors 50## SQL Configurations ##spark.sql.autoBroadcastJoinThreshold 204857600 spark.sql.warehouse.dir /user/spark/warehouse# spark.sql.hive.convertCTAS true# spark.sql.sources.default parquetspark.sql.shuffle.partitions 1024# spark.sql.hive.convertMetastoreParquet falsespark.sql.crossJoin.enabled=true## History Server Client Settings ### spark.eventLog.enabled truespark.eventLog.compress truespark.eventLog.dir hdfs:///spark2-history/ spark.yarn.historyServer.address ?:18081
spark 2.3.0加上该配置
spark.sql.statistics.fallBackToHdfs true
5 测试结果
5.1 实验数据

实验数据

显示规则
- 列1:sql statement 
- 列2:参照组结果 
- 列3:实验组结果 
- 显示规则见上图 
5.2 定性结果
- query19在参照组下没跑出结果,失误,没记下log。 
- query 77 两组皆未出结果, - spark.driver.maxResultSize 2g设置太小
- 测试只run了一轮,所以结果并不是十分严谨,[-0.1, 0.1]之间,就认为性能相当 
- 可以看到本轮测试,实验组的性能相比前一轮测试有大幅度的提升,说明诸多SQL都由SortMerge转成了Broadcast 
- 但是总体上而言,刨去“小查询”,依然有Query 9 72 88 等感受到了明显的下降。 
- query 72 怎么又有你?还能不能玩了? 
- 性能提升是应该的,性能下降就打脸了。 
6 相关分析
6.1 执行计划

quey 72 physical plan comparation
上图显示实验组在加上fallback参数后,逻辑计划除了长相不一样,但逻辑结构上已经一致了。
6.2 Job Metics对比

参照组 Job Metrics

实验组 Job Metrics
- 两轮Applications的所有Job没有task失败的记录运行良好 
- Job Id 11是两者性能的分水岭 
6.3 Stage Metrics

参照组Stage Metrics

实验组Stage Metrics
- 参照组的13、实验组的14,实为同一个Stage,主要的时差在此 

参照组Stage Metrics

实验组Stage Metrics
- 各项参数基本一致或者完全一致,除了Duration这一下,实验组完完全全的落后 

参照组 DAG

实验组 DAG
- 比较两者的DAG完全一致,逻辑上没问题,问题的原因就可能是对应的物理算子,或者Spark Core的改动产生的性能regression了。或者是我维护的分支不小心加了性能优化特性[吃了一惊的表情] 
6.4 Task Metrics

参照组 Task Id 5619

实验组 Task Id 5619
- 运气不错 Task ID 5619正巧排序后都在第一位,可以看到性能问题真正就是在task的执行过程慢,也基本印证上面6.3(3)的推断 
6.5 日志分析

日志对比5619 assigned to finished 左侧参照组 右侧实验组

接上 日志对比5619 assigned to finished
- 截取5619从开始到结束段的executor日志进行对比 
- 执行节点恰好一致 
- 与之并行的相关task也一致的调度与该节点 
- shuffle service的server也一致 
- 图中红框处,参照组Executor出现1分钟左右间隔,而实验组Executor出现3分钟左右的间隔,这时段基本可以理解为task正在吭哧吭哧的执行。 
6.6 执行计划 VS DAG

DAG
- 对比执行计划 Stage14 为最后一个SortMergeJoin的右表,对应我们Stage 13就是在做Sort的左表(中间表) 
- 所以基本可以猜测 - SortExec在2.3.0有性能regression,由于跨过了2.2相关的版本,所以并不能确定引入的时间点。
7 总结
- 对于那些没有Hive Statistics和Spark Statistics信息的表,需要注意在2.3.0之后 - spark.sql.statistics.fallBackToHdfs true去fallback,当然最好还是能去执行analyze来生成。
- SortExec物理算子应该极有可能有性能regression,需要看代码/PR的变更。后续有时间可以再带点分享。有兴趣的可以根据本文提供的线索去分析一下,如果是的话可以贡献社区。
8 后记
蜀道难,还能不能玩了?
作者:风景不美
链接:https://www.jianshu.com/p/82006ea4ca71
 
		 随时随地看视频
随时随地看视频 
				 
				 
				 
				