Impala中的代码生成技术
Cloudera Impala是一种为Hadoop生态系统打造的开源MPP(massive parallel processing)数据库,它主要为分析型查询负载而设计,而非OLTP。Impala能最大限度地利用现代硬件和高效查询执行的最新技术。LLVM下的运行时代码生成就是用来提升执行性能的技术之一。
LLVM简介
LLVM是一个编译器及相关工具的库(toolchain),它不同于独立应用式(stand-alone)的传统编译器,LLVM是模块化且可重用的。它允许Impala这样的应用在运行的进程内执行JIT(just-in-time)编译。尽管LLVM因一些特殊的能力以及著名的工具,如比GCC更优的Clang编译器,但真正使LLVM区别于其他编译器的是它的内部架构。
经典静态编译器(像多数C编译器)中,最流行的设计是前端、优化器、后端组成的三阶段设计。前端解析源码并生成抽象语法树(AST,Abstract Syntax Tree)。优化器会做很多优化来提升代码性能。后端(或称代码生成器)将代码转换成目标平台的指令集。这种模型对解释器、JIT编译器。JVM也是这种模型的一种实现,它使用字节码作为前端和优化器之间的接口。
这种经典设计对于多语言(包括源语言和目标语言)支持非常重要。只要优化器内部使用一种公共代码表示,前端和后端就能够编译任意的语言。当需要移植(porting)编译器来支持一种新语言时,只需实现一个新前端,而优化器和后端都可以重用。否则就要重新实现整个编译器,支持M种源语言*N种目标语言。
尽管各种编译器教科书中都讲到三阶段设计的种种优点,但实际上它从未被实现过。像Perl、Python、Ruby和Java的编译器实现并没有共享任何代码。此外,还有各种各样的特殊用途的编译器,例如图像处理、正则表达式等CPU密集型的子领域的JIT编译器。GCC由于混乱的代码结构而无法提取出可重用的组件,例如前端和后端重用了某些全局变量等,所以我们无法将GCC嵌入到应用程序中。下图是LLVM对三阶段设计的实现。
Impala中的LLVM
Impala使用LLVM在运行时产生完全优化并且查询特定的函数,这比通用的预编译函数有更好的性能。中的代码示例。编译时记录个数和类型都是未知的,所以中的数组offsets_和types_在每次查询开始时创建而不会改变,于是在代码生成的函数版本中,展开for循环后,这些数组中的值可以直接内联化。
Ø 内联虚函数调用:虚函数对性能的影响很大,尤其是函数很小很简单,因为它无法内联化。因此当对象实例的类型在运行时可知时,我们可以使用代码生成来取代虚函数的调用,并做内联化。这对于表达式树的求值尤为有价值。在Impala中,表达式由操作和函数的树组成,例如下图2。树中出现的每种表达式都是覆盖(override)表达式基类的函数来实现的,基类会递归地调用各个子表达式。许多表达式函数都是非常简单的,例如两数相加,于是虚函数调用的开销甚至大过表达式求值的开销。通过代码生成移除虚函数并内联化,表达式可以无需函数调用而直接求值。此外,内联后的函数使编译器做进一步的优化,例如子表达式消除等。
用LLVM生成代码
当Impala受到查询计划(query plan,由Impala的Java前端负责生成)时,LLVM会被用来在查询执行开始前,生成并编译对性能至关重要的函数的查询特定版本。LLVM主要使用IR(intermediate representation)来生成代码,例如LLVM的前端Clang C++编译器生成IR,LLVM优化IR并将其编译成机器码。IR类似于汇编语言,由一些简单的、能够直接映射成机器码的指令组成。在Impala中有两种技术来生成IR函数:使用LLVM的IRBuilder API来编程式地生成IR指令;使用CLang将C++函数交叉编译成IR。
下图是IR的例子。可以看出,IR是一种类RISC的虚拟指令集。它支持加减、比较、分支等指令。此外,IR还支持标签。但与多数RISC不同的是:
Ø LLVM是强类型的,它有一套简单的类型系统,例如i32, i32**,add i32。
Ø LLVM IR支持无限的临时寄存器,以%开头。
因为优化器不受源语言和目标平台限制,所以IR的设计也要遵守这个原则。
在LLVM中,优化器被组织成优化pass的管道,常见的pass有内联化、表达式重组、循环不变量移动等。每个pass都作为继承Pass类的C++类,并定义在一个私有的匿名namespace中,同时提供一个让外界获得到pass的函数。
我们可以决定pass的执行顺序甚至是否执行。当我们实现一种图像处理语言的JIT编译器时,我们可以去掉没用的pass。例如,如果通常都是大函数的话,就没必要浪费时间内联。如果指针很少的话,那么别名分析和内存优化就变得可有可无。但是LLVM不是万能的,PassManager本身也并不知道每个pass内部的逻辑,所以这还是由我们实现者来确定的。
参考资料
1 Runtime Code Generation in Cloudera Impala
2 The Architecture of Open Source Application
http://www.aosabook.org/en/llvm.html
Impala中的代码生成技术的更多相关文章
- 基于 Eclipse 平台的代码生成技术
------------------------------------------------------------------ 转自http://www.ibm.com/developerwor ...
- tp中使用分页技术
1 public function showList() { $m_ld = D ( 'guangxi_ld' ); $page = I ( 'get.p', 1 ); // 在配置中获取分页值 $p ...
- Web 开发中应用 HTML5 技术的10个实例教程
HTML5 作为下一代网站开发技术,无论你是一个 Web 开发人员或者想探索新的平台的游戏开发者,都值得去研究.借助尖端功能,技术和 API,HTML5 允许你创建响应性.创新性.互动性以及令人惊叹的 ...
- 【python游戏编程之旅】第七篇---pygame中的冲突检测技术
本系列博客介绍以python+pygame库进行小游戏的开发.有写的不对之处还望各位海涵. 上一个博客我们一起学习了pygame中的Sprite模块和如何加载动画:http://www.cnblogs ...
- .net中对象序列化技术浅谈
.net中对象序列化技术浅谈 2009-03-11 阅读2756评论2 序列化是将对象状态转换为可保持或传输的格式的过程.与序列化相对的是反序列化,它将流转换为对象.这两个过程结合起来,可以轻松地存储 ...
- SpreadJS 中应用 KnockoutJS 技术
SpreadJS 支持 Knockout (KO)技术, KnockoutJS 是一个使用 MVVM 模式的 JavaScript 库,允许双向数据绑定,使数据和UI界面进行实时的交互更新.关于KO的 ...
- Unity教程之再谈Unity中的优化技术
这是从 Unity教程之再谈Unity中的优化技术 这篇文章里提取出来的一部分,这篇文章让我学到了挺多可能我应该知道却还没知道的知识,写的挺好的 优化几何体 这一步主要是为了针对性能瓶颈中的”顶点 ...
- GPRS GPRS(General Packet Radio Service)是通用分组无线服务技术的简称,它是GSM移动电话用户可用的一种移动数据业务,属于第二代移动通信中的数据传输技术
GPRS 锁定 本词条由“科普中国”百科科学词条编写与应用工作项目 审核 . GPRS(General Packet Radio Service)是通用分组无线服务技术的简称,它是GSM移动电话用户可 ...
- Android中直播视频技术探究之---基础知识大纲介绍
一.前言 最近各种视频直播app到处都是,各种霸屏,当然我们也是需要体验的,关于视频直播的软件这里就不介绍了,在不是技术的人来看,直播是一种潮流,是一种娱乐方式,但是作为一个高技术的,我们除了看看,更 ...
随机推荐
- Discuz利用UC_KEY进行前台getshell
来源:http://wooyun.jozxing.cc/static/bugs/wooyun-2015-0137991.html 先通过uc_key把恶意代码保存在/uc_client/data/ca ...
- 百度URL 部分参数
[Baidu URL的部分参数] 1.Baidu Form表单如下: 2.部分参数解析 wd 查询关键字,就是你要搜索的内容. bs 上一次搜索的词或者内容: rn 搜索结果页每页显示的数目,默认 ...
- no zuo no die
#include <iostream> #include <cstring> #include <cstdio> using namespace std; name ...
- ●CodeForce 293E Close Vertices
题链: http://codeforces.com/contest/293/problem/E题解: 点分治,树状数组 大致思路和 POJ 1741 那道点分治入门题相同, 只是因为多了一个路径的边数 ...
- UVALive - 3938:"Ray, Pass me the dishes!"
优美的线段树 #include<cstdio> #include<cstdlib> #include<algorithm> #include<cstring& ...
- 51 nod 1439 互质对(Moblus容斥)
1439 互质对 题目来源: CodeForces 基准时间限制:2 秒 空间限制:131072 KB 分值: 160 难度:6级算法题 有n个数字,a[1],a[2],…,a[n].有一个集合,刚开 ...
- [APIO2014]
T1.回文树裸题. #include<cstdio> #include<iostream> #define ll long long using namespace std; ...
- Gradle学习之构建java与web项目
一.使用Gradle的java插件构建Java项目 1)Gradle插件包含了若干个接口定义和已有的任务项,语法结构:apply plugin:'插件名' ,此处我们定义插件 apply plugin ...
- SpringCloud学习之feign
一.关于feigin feigin是一种模板化,声明式的http客户端,feign可以通过注解绑定到接口上来简化Http请求访问.当然我们也可以在创建Feign对象时定制自定义解码器(xml或者jso ...
- pix2code:从截图生成图形用户界面代码
将设计人员创建的图形用户界面截图转换为计算机代码是开发人员为构建定制的软件,网站和移动应用程序而进行的一项典型任务. 在本文中,我们展示了深入的学习方法可以用于训练一个端对端的模型,以便从三个不同的平 ...