轻量级高性能的表达式求值器——aviator发布2.0

    aviator是一个轻量级的、高性能的Java表达式求值器,主要应用在如工作流引擎节点条件判断、MQ中的消息过滤以及某些特定的业务场景。

    自从上次发布1.0后,还发过1.01版本,不过都没怎么宣传。这次发布一个2.0的里程碑版本,主要改进如下:

1、完整支持位运算符,与java完全一致。位预算符对实现bit set之类的需求还是非常必须的。

2、性能优化,平均性能提升100%,函数调用性能提升200%,最新的与groovy和JEXL的性能测试看这里

http://code.google.com/p/aviator/wiki/Performance

3、添加了新函数,包括long、double、str用于类型转换,添加了string.indexOf函数。

4、完善了用户手册,更新性能测试。

 

下载地址: http://code.google.com/p/aviator/downloads/list

项目主页:  http://code.google.com/p/aviator/

用户指南:  http://code.google.com/p/aviator/w/list

性能报告:  http://code.google.com/p/aviator/wiki/Performance

源码:          https://github.com/killme2008/aviator

 

Maven引用(感谢许老大的帮助):

    <dependency>
            <groupId>com.googlecode.aviator</groupId>
            <artifactId>aviator</artifactId>
                        <version>2.0</version>
    </dependency>

     这个项目目前用在我们的MQ产品中做消息过滤,也有几个公司外的用户告诉我他们也在用,不过估计不会很多。有这种需求的场景还是比较少的。这个项目实际上是为我们的MQ定制的,我主要想做到这么几点:

(1)控制用户能够使用的函数,不允许调用任何不受控制的函数。

(2)轻量级,不需要嵌入groovy这么大的脚本引擎,我们只需要一个剪裁过的表达式语法即可。

(3)高性能,最终的性能在某些场景比groovy略差,但是已经非常接近。

(4)易于扩展,可以容易地添加函数扩展功能。语法相对固定。

(5)函数的调用避免使用反射。因此没使用dot运算符的函数调用方式,而是更类似c语言和lua语言的函数调用风格。函数是一等公民,seq库的风格很符合我的喜好。

  seq这概念来自clojure,我将实现了java.util.Collection接口的类和数组都称为seq集合,可以统一使用seq库操作。例如假设我有个list:

        Map<String, Object> env = new HashMap<String, Object>();
        ArrayList<Integer> list = new ArrayList<Integer>();
        list.add(3);
        list.add(100);
        list.add(-100);
        env.put("list", list);

   可以做这么几个事情,度量大小:

count(list)

   判断元素是否存在:

include(list,3)

   过滤元素,返回大于0的元素组成的seq:

filter(list,seq.gt(0))

   对集合里的元素求和,应用reduce:

reduce(list,+,0)

   遍历集合元素并打印:

map(list,println)

   最后,你还可以排序:

sort(list)

    这些函数类似FP里的高阶函数,使用起来还是非常爽的。

    对函数调用的优化,其实只干了一个事情,原来函数调用我是将所有参数收集到一个list里面,然后再转成数组元素交给AviatorFunction调用。这里创建了两个临时对象:list和数组。这其实是没有必要的,我只要在AviatorFunction里定义一系列重载方法,如:

   public AviatorObject call(Map<String, Object> env);

    public AviatorObject call(Map<String, Object> env, AviatorObject arg1);

    public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2);

    public AviatorObject call(Map<String, Object> env, AviatorObject arg1, AviatorObject arg2, AviatorObject arg3);

    

   就不需要收集参数,而是直接invokeinterface调用AviatorFunction相应的重载方法即可。我看到在JRuby和Clojure里的方法调用都这样干的。过去的思路走岔了。最终也不需要区分内部的method和外部的function,统一为一个对象即可,进一步减少了对象创建的开销。

文章转自庄周梦蝶  ,原文发布时间 2011-07-13

时间: 2024-09-20 07:47:08

轻量级高性能的表达式求值器——aviator发布2.0的相关文章

浅谈C/C++ 语言中的表达式求值_C 语言

经常可以在一些讨论组里看到下面的提问:"谁知道下面C语句给n赋什么值?" m = 1; n = m+++m++; 最近有位不相识的朋友发email给我,问为什么在某个C++系统里,下面表达式打印出两个4,而不是4和5: a = 4; cout << a++ << a; C++ 不是规定 << 操作左结合吗?是C++ 书上写错了,还是这个系统的实现有问题? 注:运行a = 4; cout << a++ << a; 如在Visua

表达式求值、表达式转二叉树

1.后序表达式求值: 后续表达式(逆波兰式)的特点:没有括号. 求值方法: 从前向后扫, 遇到操作数压栈: 遇到操作符,从栈中取出2个操作数运算,结果压栈. 最终栈中所剩的数为结果. 2.中序表达式求值 我们先来定义运算符的优先级: ( +,- *,/,% 从上到下依次升高 准备2个栈,一个专门存放运算符,另一个专门存放操作数. 1.遇到),那么退栈计算到(为止.结果压栈. 2.遇到运算数.那么压栈. 3.如果当前运算符优先级低于栈顶运算符.那么计算栈顶运算符并将结果压栈. 4.否则压栈. 计算

MYSQL表达式求值和MYSQL类型转换

    2.4 表达式求值和类型转换    MySQL允许编写包括常量.函数调用和表列引用的表达式.这些值可利用不同类型的运算符进行组合,诸如算术运算符或比较运算符.表达式的项可用圆括号来分组.表达式在SELECT 语句的列选择列表和WHERE 子句中出现得最为频繁,如下所示:    所选择的每列给出了一个表达式,如WHERE 子句中所示的那样.表达式也出现在DELETE 和UPDATE语句的WHERE 子句中,以及出现在INSERT 语句的VALUES( ) 子句中.    在MySQL遇到一

后缀表达式求值及校验

摘要: 本程序是一个完整的后缀表达式计算,主要用栈的操作实现,本程序封装了CStack类实现栈的操作,本程序最大的特色在于运用动态监视表达式的算法对表达式进行数据校验,对一切合法的表达式进行计算,检验出所有任何非法表达式并提示. 关键字:后缀表达式,校验 题目:后缀表达式求值. 要求:输入后缀表达式,输入为整数和四则运算,输出计算结果. 例如: 输入:2 3 * 1 - 输出:5 分析:2*3-1=5 输入:1 2 + 5 4 * 3 - * 6 - 输出:45 分析:(1+2)*(5*4-3)

C#算术表达式求值

算术表达式求值是一个经典的问题,很多学习编程的人都对此不陌生.本来我并不想写一个算术表达式求值的算法.在网上我看到了一篇文章,名叫<快速精确的对数学表达式求值>( http://www-128.ibm.com/developerworks/cn/java/j-w3eva/ ).才有兴趣着一个玩玩.写来写去,觉得真得很经典.所以把我写的代码拿出来让大家看看吧.因为时间较紧.所以变量名没有做得很规范. w3eavl是用JAVA写得,我用C#把它重写了一下.基本上能用,只是三角函数/反三角函数/双曲

网易游戏开发笔试题:lisp表达式求值

一.文章来由 按照惯例有这个section,但是木有什么可写的,一道笔试题而已~~~ 二.lisp表达式求值 题目如下: 分析: 初看题目,这就是一道很简单的ACM字符处理题,有点类似中缀表达式求值.但是字符题非常需要细心,一不小心就出错,我的实现是用的栈实现,而且只用了一个栈,所以实现起来,要处理字符和括号,还有操作符,捉襟见肘...应该直接用两个栈实现,一个存操作数,一个存操作符,这样就方便了~~ 上代码: #include <iostream> #include <string&g

bug-这是我写的表达式求值,在编译器中运行是对的,但在刷题系统中却说是错,求打什么呢帮我找找Bug

问题描述 这是我写的表达式求值,在编译器中运行是对的,但在刷题系统中却说是错,求打什么呢帮我找找Bug 2C #include""stdio.h""#include""stdlib.h""#include""malloc.h""#include""string.h""#include""math.h""#de

如何应用堆栈的思想实现表达式求值?

问题描述 如何应用堆栈的思想实现表达式求值?例:输入(3*(1+2-3)*4)输出结果! 解决方案 解决方案二:这个是典型的数据结构的问题数据结构书上面都会有这样的先把上述的表达式转换为"后缀表达式"312+3-*4*数字全部压入栈:碰到运算符,在栈中提取最上面两个数字,做运算,然后放回栈当栈中没有数据的时候,运算完成大清早的脑子还混乱,不知有没有大漏洞解决方案三:恩--谢谢你啊!以后有问题请多多指教

关于c++表达式求值的一些问题,求大神解答

问题描述 关于c++表达式求值的一些问题,求大神解答 看完裘老师的这篇关于表达式求值的帖子C/C++表达式求值.有个地方不明白. 有这样一句话 看下面例子:(a + b) * (c + d) fun(a++, b, a+5) 这里"*"的两个运算对象中哪个先算?fun及其三个参数按什么顺序计算?对第一个表达式,采用任何计算顺序都没关系,因为其中的子表达式都是引用透明的.第二个例子里的实参表达式出现了副作用,计算顺序就非常重要了.少数语言明确规定了运算对象的计算顺序(Java规定从左到右