SlideShare a Scribd company logo
1 of 31
Aviator——飞行家 轻量级的表达式执行引擎 伯岩(boyan@taobao.com)
提纲 起源 语言 性能 结语
起源 Notify引入AMP订阅模型,支持header表达式匹配 类似JMS规范的selector机制,通过表达式过滤消息。 Notify在服务端,JMS selector在客户端 第一个版本使用groovy 优点:groovy是图灵完备的语言,淘宝内部使用较多,用户相对熟悉 缺点:  groovy-all打包引用的依赖库太多,太大。Notify并不需要一门完整的语言。
起源 初步设想实现一个表达式引擎 基于ASM动态编译生成字节码,并交给JVM执行。 非图灵完备,对java语法剪裁 没有赋值,没有位运算,没有条件语句(除了三元运算符),没有循环语句 仅支持逻辑运算、算术运算、正则匹配、函数调用和三元表达式
起源
项目信息 名称:Aviator(飞行家) 主页:http://code.google.com/p/aviator/ 协议:LGPL 大小: 403K (包括asm) Groovy 1.6.4 (4.3M,不包括依赖包) 其他信息 单元测试覆盖率 90.1% LOC:14000+ Classes: 131
语言 AviatorEvaluator 入口类 AviatorEvaluator.execute() AviatorEvaluator.execute(env) env为表达式中变量的值 env为Map<String,Object>  AviatorEvaluator.compile(string)  AviatorEvaluator.compile(string,cached) cached 是否缓存编译结果
Hello world String name= args[0];  Map<String, Object> env = new HashMap<String, Object>();  env.put(" name ", name);  String result = (String) AviatorEvaluator.execute(" 'hello ' + name ", env);  System.out.println(result);
数据类型
算术运算 1+2+3 6-3+4 6-(3+4) 1*2*3+1/2/3+100%3 (1+2/(3-4)*pi-2*pi*r+pi/j*i%100
逻辑运算和关系运算 true false && true  true || false 短路规则 messageType==‘trade-cteate’ && !committed !bool a>b  a>=nil  , 永远返回true a<b  a<=nil ,返回false,除非a为nil a==b  a!=nil
三元操作符 ?: 1>0? 1:-1 bool? (a+b) : (a-b) !t? i>0? f:ch : f>3?email:ch 多层嵌套 !t? (i>0? f:ch) :( f>3?email:ch) 使用括号
正则匹配 类Perl,Ruby的匹配语法,匹配成功返回true,否则返回false 正则表达式语法与Java相同 匹配成功,分组存入$digit的变量中,后续可获取 '10'=~/^d+$/ 'ABC'=~/^[A-Za-z]+$/ '<html>hello</html>'=~/<(.*)>.*</1>|<(.*) />/ email=~/([w0-8]+)@w+[.w+]+/ ? $1:'unknow‘  $1 指向匹配的第一个分组,也就是用户名  $0 指向整个匹配的字符串
字符串运算 ‘hello’+1   == ‘hello1’ ‘hello ’ + ‘world’ == ‘hello world’ ‘hello ’ + nil  == ‘hello null’ i+’hello’  == i.toString() + ‘hello’ 任何对象与String相加,结果为String ‘abc’ > ‘bac’ ‘abc’ ==‘abc’ 字符串比较可以直接使用关系运算符 date > '2009-12-20 00:00:00:00‘ 字符串可以跟java.util.Date直接比较,字符串形式必须为yyyy-MM-dd HH:mm:ss:SS
访问数组、List和Map 通过[]可直接访问数组或者java.util.List中的元素 a[0] list[0]-a[1]*list[1] java.util.Map可以通过map.key的形式访问Map中key对应的value property.long property.short
变量的嵌套访问 foo.bar.i 变量foo中的bar字段中的i字段的属性值 foo.date.year foo.date.month 变量foo中的java.util.Date对象的year值和month值 这是利用cmmons-beanutils反射
函数调用 sysdate() rand() println(a) print(a) string.contains(‘hello’,’ell’) string.length(a) math.pow(3,2.0) math.sin(30) ……etc,目前有system、math和seq三种标准库函数
Seq库 java.util.Collection子类及数组称为seq集合 count(seq) include(seq,element) sort(seq) 返回新的seq,原来的seq不变 map(seq,fun) reduce(seq,fun,init) filter(seq,fun) 返回新的seq,原来的seq不变
Seq库 map(s,println) map(s,-)  求相反数组成的集合 filter(s,seq.gt(3))     value>3组成的集合 filter(s,seq.exists()) 非nil组成的集合 reduce(s,+,0) 求和 reduce(s,*,1)  阶乘 include(s,’hello’)
自定义函数 class AddFunction implements AviatorFunction 自定义函数实现AviatorFunction接口 public AviatorObject call(Map<String, Object> env, AviatorObject... args) 实际的调用操作,args为传入的参数 public String getName() 返回函数名,表达式使用该名称 AviatorEvaluator.addFunction(new AddFunction()); 注册函数 AviatorEvaluator.execute("add(1,2)")); AviatorEvaluator.execute("add(add(1,2),100)"));
类型转换规则 Java的byte short int long都转化为Long类型,Java的float,double都将转化为Double类型。Java的char String都将转化为String。Java的null都将转为nil。  当两个操作符都是Double或者都是Long的时候,各自按照Double或者Long的类型执行  当两个操作符中某一个是Double的时候,另一个操作数也将转换成Double,按照Double类型执行。  任何类型与String相加,结果为String  任何类型都比nil大,除了nil本身。  nil在打印或者与字符串相加的时候,显示为null  形如"yyyy-MM-dd HH:mm:ss:SS"的字符串,在与java.util.Date做比较的时候将尝试转换成java.util.Date对象比较。  没有规定的类型转换操作,除了未知的变量类型之间,都将抛出异常。
两种模式 编译速度优先 AviatorEvaluator.setOptimize(AviatorEvaluator.COMPILE) 运行效率优先 AviatorEvaluator.setOptimize(AviatorEvaluator.EVAL)
性能 测试场景 不同表达式在不同引擎执行1000万次的时间。 预热 预先编译,再执行 部分测试的表达式OGNL抛出异常 测试引擎 Groovy 1.6.4 MVEL    2.0.17   Aviator(运行速度优先) 1.0.0-final OGNL      2.7.1
1000+100.0*99-(600-3*15)%(((68-9)-3)*2-100)+10000%7*71
i * pi + (d * b - 199) / (1 - d * pi) - (2 + 100 - i / pi) %
'A' == 'A' || 'B' == 'B' && 'ABCD' == t &&  'A' == 'A'
i>pi || !bool || d+pi*i>1000 && b<0
thiz.vars.i+100-(thiz.vars.bool?thiz.vars.d:thiz.vars.pi)-(thiz.vars.d+thiz.vars.pi)+t
小结 Aviator在编译执行常量组成的表达式非常快速,直接在编译阶段执行出结果。 Aviator的算术运算性能还不错,考虑到它做了不少类型转换的工作。 Aviator的关系运算和逻辑运算的效率较低,这是未来需要改进的地方。 总体来讲,Aviator的效率介于groovy和mvel之间,ognl新版本仍然有不少BUG。
Summary 轻量级 字节码生成 支持算术、逻辑和关系运算 支持三元表达式 支持语言层面的正则匹配 函数调用和自定义函数 函数式的集合访问和操作 性能满足要求
Aviator——轻量级表达式执行引擎

More Related Content

Viewers also liked

QCon - 一次 Clojure Web 编程实战
QCon - 一次 Clojure Web 编程实战QCon - 一次 Clojure Web 编程实战
QCon - 一次 Clojure Web 编程实战dennis zhuang
 
我在 Mac 上的常用开发工具
我在 Mac 上的常用开发工具我在 Mac 上的常用开发工具
我在 Mac 上的常用开发工具dennis zhuang
 
Clojure 1.8 Direct-Linking WWH
Clojure 1.8  Direct-Linking  WWHClojure 1.8  Direct-Linking  WWH
Clojure 1.8 Direct-Linking WWHdennis zhuang
 
Java 与 CPU 高速缓存
Java 与 CPU 高速缓存Java 与 CPU 高速缓存
Java 与 CPU 高速缓存dennis zhuang
 

Viewers also liked (11)

Clojure的魅力
Clojure的魅力Clojure的魅力
Clojure的魅力
 
Clojure概览
Clojure概览Clojure概览
Clojure概览
 
QCon - 一次 Clojure Web 编程实战
QCon - 一次 Clojure Web 编程实战QCon - 一次 Clojure Web 编程实战
QCon - 一次 Clojure Web 编程实战
 
我在 Mac 上的常用开发工具
我在 Mac 上的常用开发工具我在 Mac 上的常用开发工具
我在 Mac 上的常用开发工具
 
Clojure 1.8 Direct-Linking WWH
Clojure 1.8  Direct-Linking  WWHClojure 1.8  Direct-Linking  WWH
Clojure 1.8 Direct-Linking WWH
 
Nio trick and trap
Nio trick and trapNio trick and trap
Nio trick and trap
 
Java 与 CPU 高速缓存
Java 与 CPU 高速缓存Java 与 CPU 高速缓存
Java 与 CPU 高速缓存
 
Elixir introd
Elixir introdElixir introd
Elixir introd
 
Mesos intro
Mesos introMesos intro
Mesos intro
 
Erlang scheduler
Erlang schedulerErlang scheduler
Erlang scheduler
 
Hystrix 介绍
Hystrix 介绍Hystrix 介绍
Hystrix 介绍
 

Aviator——轻量级表达式执行引擎