表达式引擎性能比较

表达式引擎性能比较

表达式引擎选型

选择3种主要的表达式引擎进行性能对比,从而选择最优表达式引擎和最优方案。常用的3中规则引擎:QLExpress、MEVL、JUEL。

性能测试

性能测试维度:

  • 表达式引擎维度:主要采用了3种引擎的5种实现方式,即QLExpress 使用缓存; mvel 不编译; mvel 先编译; mvel 先编译,且指定输入值类型; juel 指定输入值类型。注:QLExpress 不使用缓存的话,性能非常低,就不再进行对比测试。
  • 表达式维度:主要采用了3种类型的表达式,后续的大多数需求,都属于这3种方式。即:
    • 最常见的场景(多个条件进行and操作): a<100 && b>=100 && c<=123,
    • 包含特殊的操作(contains):a<100 && b>=100 && c<=123 && stringList.contains(str)
    • 一个稍微复杂一点的语法树:a>1 && ((b>1 || c<1) || (a>1 && b<1 && c>1))

测试方式

10次循环,每次循环执行这5种方式10万次,即每种方式执行100万次。为了保证一定的差异性,变量赋值的时候,采用变化的值。代码详见附录。

执行结果:

对结果进行可视化,很显然Mvel不编译方式耗时最高。

为了方便查看,将Mvel不编译方式过滤掉,得到下图。得到以下结论:

  • 性能高低顺序为:mvel 先编译,且指定输入值类型 > mvel 先编译 > juel 指定输入值类型 > QLExpress 使用缓存 > mvel 不编译
  • juel 指定输入值类型性能也可以接受,但是在使用了contains操作后,性能明显降低很多。

结论

mvel 先编译,且指定输入值类型方式性能为最优,采用该方式作为表达式引擎的实现方式。但是,采用自己实现一层缓存:用来缓存预编译的结果,同时,采用2小时无访问,则更新缓存的策略。缓存使用Guava Cache实现。

注: 1. QLExpress自身实现了缓存机制,如果性能要求没那么高的话,也可以采用该方式。 2. 如果规则非常多,比如到了亿级别的规模,并且基本不复用规则的话,就没有必要先编译并缓存了。或者调整缓存策略。

附录

机器配置

1
2
3
4
MacBook Pro (13-inch, 2017, Two Thunderbolt 3 ports)
处理器 2.3 GHz Intel Core i5
内存 8 GB 2133 MHz LPDDR3
图形卡 Intel Iris Plus Graphics 640 1536 MB

表达式引擎版本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<!-- https://mvnrepository.com/artifact/org.mvel/mvel2 -->
<dependency>
<groupId>org.mvel</groupId>
<artifactId>mvel2</artifactId>
<version>2.4.0.Final</version>
</dependency>

<!-- https://mvnrepository.com/artifact/ognl/ognl -->
<dependency>
<groupId>ognl</groupId>
<artifactId>ognl</artifactId>
<version>3.2.4</version>
</dependency>

<!-- https://mvnrepository.com/artifact/de.odysseus.juel/juel-api -->
<dependency>
<groupId>de.odysseus.juel</groupId>
<artifactId>juel-api</artifactId>
<version>2.2.7</version>
</dependency>

<!-- https://mvnrepository.com/artifact/de.odysseus.juel/juel-impl -->
<dependency>
<groupId>de.odysseus.juel</groupId>
<artifactId>juel-impl</artifactId>
<version>2.2.7</version>
</dependency>

Java代码

详见: https://github.com/DanielJyc/expression-language-compare/blob/master/java/src/Test.java

参考文档

坚持原创技术分享,您的支持将鼓励我继续创作!