java fel_Java表达式引擎fel/groovy/expression4j/java脚本引擎的性能对比【原创】

又是性能对比,最近跟性能较上劲了。

产品中需要用到数学表达式,表达式不复杂,但是对性能要求比较高。选用了一些常用的表达式引擎计算方案,包含:java脚本引擎(javax/script)、groovy脚本引擎、Expression4j、Fel表达式引擎。

其中java脚本引擎使用了解释执行和编译执行两种方式、groovy脚本只采用了编译执行(解释执行太慢)、Fel采用了静态参数和动态参数两种方式。以下为测试代码:public class ExpressionTest extends BaseTest {

private int count = 100000;

//javax的编译执行,效率比解释执行略高?为什么才略高??

@Test

public void testCompiledJsScript() throws Throwable {

javax.script.ScriptEngine se = new ScriptEngineManager().getEngineByName("js");

Compilable ce = (Compilable) se;

CompiledScript cs = ce.compile("a*b*c");

Bindings bindings = se.createBindings();

bindings.put("a", 3600);

bindings.put("b", 14);

bindings.put("c", 4);

long start = System.currentTimeMillis();

for (int i = 0; i 

cs.eval(bindings);

}

System.out.println(System.currentTimeMillis() - start);

}

//javax script解释执行

@Test

public void testJsScript() throws Throwable {

javax.script.ScriptEngine se = new ScriptEngineManager().getEngineByName("js");

Bindings bindings = se.createBindings();

bindings.put("a", 3600);

bindings.put("b", 14);

bindings.put("c", 4);

long start = System.currentTimeMillis();

for (int i = 0; i 

se.eval("a*b*c", bindings);

}

System.out.println(System.currentTimeMillis() - start);

}

//groovy的编译执行

@Test

public void testGroovy() {

//这里的ScriptEngine和GroovyScriptEngine是自己编写的类,不是原生的

ScriptEngine se = this.getBean(GroovyScriptEngine.class);

Map paramMap = new HashMap();

paramMap.put("param", 5);

//ScriptEngine首次执行会缓存编译后的脚本,这里故意先执行一次便于缓存

se.eval("3600*34*param", paramMap);

long start = System.currentTimeMillis();

for (int i = 0; i 

se.eval("3600*34*param", paramMap);

}

System.out.println(System.currentTimeMillis() - start);

}

//Expression4J的表达式引擎,这里是通过函数的方式,有点特别

@Test

public void testExpression4j() throws Throwable {

Expression expression = ExpressionFactory.createExpression("f(a,b,c)=a*b*c");

System.out.println("Expression name: " + expression.getName());

System.out.println("Expression parameters: " + expression.getParameters());

MathematicalElement element_a = NumberFactory.createReal(3600);

MathematicalElement element_b = NumberFactory.createReal(34);

MathematicalElement element_c = NumberFactory.createReal(5);

Parameters parameters = ExpressionFactory.createParameters();

parameters.addParameter("a", element_a);

parameters.addParameter("b", element_b);

parameters.addParameter("c", element_c);

long start = System.currentTimeMillis();

for (int i = 0; i 

expression.evaluate(parameters);

}

System.out.println(System.currentTimeMillis() - start);

}

//fel的表达式引擎(静态参数,同上面)

@Test

public void felTest() {

FelEngine e = FelEngine.instance;

final FelContext ctx = e.getContext();

ctx.set("a", 3600);

ctx.set("b", 14);

ctx.set("c", 5);

com.greenpineyu.fel.Expression exp = e.compile("a*b*c", ctx);

long start = System.currentTimeMillis();

Object eval = null;

for (int i = 0; i 

eval = exp.eval(ctx);

}

System.out.println(System.currentTimeMillis() - start);

System.out.println(eval);

}

//fel表达式引擎(动态参数,这里动态参数的产生和变量改变都会消耗时间,因此这个测试时间不准确,只是验证对于动态参数的支持)

@Test

public void felDynaTest() {

FelEngine e = FelEngine.instance;

final FelContext ctx = e.getContext();

ctx.set("a", 3600);

ctx.set("b", 14);

ctx.set("c", 5);

com.greenpineyu.fel.Expression exp = e.compile("a*b*c", ctx);

long start = System.currentTimeMillis();

Object eval = null;

Random r = new Random();

for (int i = 0; i 

ctx.set("a", r.nextInt(10000));

ctx.set("b", r.nextInt(100));

ctx.set("c", r.nextInt(100));

eval = exp.eval(ctx);

}

System.out.println(System.currentTimeMillis() - start);

System.out.println(eval);

}

public static void main(String[] args) throws Throwable {

ExpressionTest et = new ExpressionTest();

//执行100W次的测试

et.count = 1000000;

et.testCompiledJsScript();

et.testJsScript();

et.testExpression4j();

et.testGroovy();

et.felTest();

}

}

测试结果如下:表达式引擎执行时间(毫秒)备注

java脚本引擎编译后执行7662

java脚本引擎解释执行10609

expression4j578

groovy编译执行224

fel静态参数19

fel动态参数107该项测试比较不公平,随机数的产生以及参数的变更也会占用一定时间,测试目的只是为了验证是不是存在静态优化,从而导致静态性能远高于动态性能的情况。

结论:

从以上性能对比来看(抛开表达式的功能),fel明显占据很大优势,groovy和expression4j也是可以接受的。java脚本引擎的执行偏慢。因此,对于表达式不是很复杂性能要求高的情况下,推荐使用fel或者groovy编译执行的方式。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值