Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

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

5,806 views

Published on

Aviator——轻量级表达式执行引擎,介绍和示例

Published in: Technology
  • Be the first to comment

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

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

×