Spark Codegen原理分析

1、背景

Spark Codegen是在CBO&RBO后,将算子的底层逻辑用代码来实现的一种优化。
具体包括Expression级别和WholeStage级别的Codegen。

2、举例说明
① Expression级别:摘一个网上的例子:x + (1 + 2)

用scala代码表示:

Add(Attribute(x), Add(Literal(1), Literal(2)))

语法树如下:
在这里插入图片描述
递归求值这棵语法树的常规代码如下:

tree.transformUp {
   
  case Attribute(idx) => Literal(row.getValue(idx))
  case Add(Literal(c1),Literal(c2)) => Literal(c1+c2)
  case Literal(c) => Literal(c)
}

执行上述代码需要做很多类型匹配、虚函数调用、对象创建等额外逻辑,这些overhead远超对表达式求值本身。
为了消除这些overhead,Spark Codegen直接拼成求值表达式的java代码并进行即时编译。具体分为三个步骤:

  1. 代码生成。根据语法树生成java代码,封装在wrapper类中:
... // class wrapper
row.getValue(idx) + (1 + 2)
... // class wrapper
  1. 即时编译。使用Janino框架把生成代码编译成class文件。
  2. 加载执行。最后加载并执行。

优化前后性能有数量级的提升。
在这里插入图片描述

② WholeStage级别 举一个稍微复杂的例子,并详细分析一下

看了上面的例子,应该先有了一个大致的印象,接下来看下:
SQL:

select * from test.zyz where id=1;

表结构:

CREATE TABLE `test.zyz`(
  `id` int,
  `name` string)
PARTITIONED BY (
  `pt` int)
ROW FORMAT SERDE
  'org.apache.hadoop.hive.ql.io.parquet.serde.ParquetHiveSerDe'
STORED AS INPUTFORMAT
  'org.apache.hadoop.hive.ql.io.parquet.MapredParquetInputFormat'
OUTPUTFORMAT
  'org.apache.hadoop.hive.ql.io.parquet.MapredParquetOutputFormat'

执行计划:

Found 1 WholeStageCodegen subtrees.
== Subtree 1 / 1 ==
*(1) Project [id#11, name#12, pt#13]
+- *(1) Filter (isnotnull(id#11) && (id#11 = 1))
   +- *(1) FileScan parquet test.zyz[id#11,name#12,pt#13] Batched: true, Format: Parquet, Location: CatalogFileIndex[hdfs://nameservice1/user/hive/wareh
  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值