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到处都是,各种霸屏,当然我们也是需要体验的,关于视频直播的软件这里就不介绍了,在不是技术的人来看,直播是一种潮流,是一种娱乐方式,但是作为一个高技术的,我们除了看看,更 ...
随机推荐
- [HNOI 2013]比赛
Description 沫沫非常喜欢看足球赛,但因为沉迷于射箭游戏,错过了最近的一次足球联赛.此次联 赛共N支球队参加,比赛规则如下: (1) 每两支球队之间踢一场比赛. (2) 若平局,两支球队各得 ...
- codesforces 671D Roads in Yusland
Mayor of Yusland just won the lottery and decided to spent money on something good for town. For exa ...
- ionic 禁用 手势 滑动返回
$ionicConfigProvider.views.swipeBackEnabled(false); 在 应用的 config里面 配置下 上面的那句话 就OK了.
- Mysql锁机制--写锁
Mysql 系列文章主页 =============== 1 准备数据 1.1 建表 1.1.1 建立 Employee表 DROP TABLE IF EXISTS employee; CREATE ...
- 【vuejs深入二】vue源码解析之一,基础源码结构和htmlParse解析器
写在前面 一个好的架构需要经过血与火的历练,一个好的工程师需要经过无数项目的摧残. vuejs是一个优秀的前端mvvm框架,它的易用性和渐进式的理念可以使每一个前端开发人员感到舒服,感到easy.它内 ...
- WEB中间件--tomcat爆破,burp和python脚本
1.tomcat 用burpsuit进行弱口令爆破 先抓包 发送到inturder payload type 选择custom iterater 第一个payload选用户名文件,第二个payload ...
- Socket.io应用之联网拖拽游戏
服务器端代码: const express=require('express'); const http=require('http'); const sio=require('socket.io') ...
- 线性表 linear_list 顺序存储结构
可以把线性表看作一串珠子 序列:指其中的元素是有序的 注意last和length变量的内在关系 注意:将元素所占的空间和表长合并为C语言的一个结构类型 静态分配的方式,分配给一个固定大小的存储空间之后 ...
- MySQL my.cnf 配置文件注释
以下是my.cnf配置文件参数解释 [client] port = 3309socket = /home/longxiben ...
- hive 存储,解析,处理json数据
hive 处理json数据总体来说有两个方向的路走 1.将json以字符串的方式整个入Hive表,然后通过使用UDF函数解析已经导入到hive中的数据,比如使用LATERAL VIEW json_tu ...