WastEl 表达式引擎性能测试 - 每秒千万次运算超强性能
简介
WAST是一个高性能Java工具集库包,包括JSON、YAML、CSV、HttpClient、JDBC和EL引擎.
下面是单独对WastEl性能测试,测试环境window10 处理器i5 JDK1.8 单线程 idea工具(服务器配置性能中等)
maven依赖
<dependency>
<groupId>io.github.wycst</groupId>
<artifactId>wast</artifactId>
<version>0.0.18</version>
</dependency>
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-core</artifactId>
<version>1.36</version>
</dependency>
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-generator-annprocess</artifactId>
<version>1.36</version>
</dependency>
测试代码
import io.github.wycst.wast.common.expression.CacheableExpression;
import io.github.wycst.wast.common.expression.Expression;
import io.github.wycst.wast.common.expression.compile.CompilerExpression;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;
import org.openjdk.jmh.runner.options.TimeValue;
import java.util.concurrent.TimeUnit;
/**
* @Created by wangyc
*/
public class WastElPerSecondJmhTest {
final static String staticEl = "1+2";
final static String dynamicsEl = "a+a+a+b+b";
final static Expression wastParsedEl;
final static Expression wastCompiledEl;
final static Fact fact = new Fact();
public static class Fact {
public int a = 1;
public int b = 2;
public int c = 3;
}
static {
wastParsedEl = Expression.parse(dynamicsEl);
wastCompiledEl = CompilerExpression.createEnvironment()
.objectParameterClass(Fact.class)
.variableTypes(int.class, "a", "b")
.compile(dynamicsEl);
}
@Benchmark
public Object staticExpr() {
return Expression.eval(staticEl);
}
@Benchmark
public Object cacheableStaticExpr() {
return CacheableExpression.eval(staticEl);
}
@Benchmark
public Object dynamicsDirect() {
return Expression.evalParameters(dynamicsEl, fact.a, fact.b);
}
@Benchmark
public Object dynamicsParsedWithPojo() {
return wastParsedEl.evaluate(fact);
}
@Benchmark
public Object dynamicsParsedWithParameters() {
return wastParsedEl.evaluateParameters(fact.a, fact.b);
}
@Benchmark
public Object compileParameters() {
return wastCompiledEl.evaluateParameters(fact.a, fact.b);
}
@Benchmark
public Object compilePojo() {
return wastCompiledEl.evaluate(fact);
}
@Benchmark
public Object javaCode() {
return fact.a + fact.a + fact.a + fact.b + fact.b;
}
public static void main(String[] args) throws RunnerException {
System.out.println("staticExpr result " + Expression.eval(staticEl));
System.out.println("cacheableStaticExpr result " + CacheableExpression.eval(staticEl));
System.out.println("dynamicsDirect result " + Expression.evalParameters(dynamicsEl, fact.a, fact.b));
System.out.println("dynamicsParsedWithPojo result " + wastParsedEl.evaluate(fact));
System.out.println("dynamicsParsedWithParameters result " + wastParsedEl.evaluateParameters(fact.a, fact.b));
Options options = new OptionsBuilder()
.include(WastElPerSecondJmhTest.class.getName())
.mode(Mode.Throughput)
.timeUnit(TimeUnit.SECONDS)
.warmupTime(TimeValue.seconds(3))
.measurementTime(TimeValue.seconds(3))
.forks(1)
.build();
new Runner(options).run();
}
}
运行结果(ops/s 每秒运算次数)
Benchmark Mode Cnt Score Error Units
WastElPerSecondJmhTest.cacheableStaticExpr thrpt 5 171657564.516 ± 7995468.134 ops/s
WastElPerSecondJmhTest.compileParameters thrpt 5 241759348.205 ± 15257569.604 ops/s
WastElPerSecondJmhTest.compilePojo thrpt 5 337235732.558 ± 15465646.140 ops/s
WastElPerSecondJmhTest.dynamicsDirect thrpt 5 2303974.920 ± 54792.033 ops/s
WastElPerSecondJmhTest.dynamicsParsedWithParameters thrpt 5 33469025.187 ± 433401.164 ops/s
WastElPerSecondJmhTest.dynamicsParsedWithPojo thrpt 5 17290195.897 ± 502910.746 ops/s
WastElPerSecondJmhTest.javaCode thrpt 5 336520348.857 ± 14309011.816 ops/s
WastElPerSecondJmhTest.staticExpr thrpt 5 15374869.767 ± 325368.159 ops/s
结论
- 解析模式下执行静态表达式在无缓存的情况下每秒1.5千万次(注包含解析过程)
- 解析模式下执行静态表达式在有缓存的情况下每秒1.6亿次(只解析一次)
- 编译模式下包含4次加法运算的动态表达式每秒最高3亿次基本上和java代码每秒运行的次数持平
第三方测试目前只加入过express-benchmark (作者闲.大赋),结果有两月没更新了,无奈自己贴下个人运行的结果
public class Test {
public static void main(String[] args) throws Exception {
org.openjdk.jmh.Main.main(args);
}
}
下面是在JDK17下运行 的结果(每秒运算次数)
Benchmark Mode Cnt Score Error Units
Aviator.forExpresss thrpt 5 394144.816 ± 43654.175 ops/s
Aviator.ifExpresss thrpt 5 3963746.142 ± 131093.900 ops/s
Aviator.simpleExpress thrpt 5 3308604.053 ± 25862.339 ops/s
Beetl.forExpresss thrpt 5 1443597.295 ± 41988.440 ops/s
Beetl.ifExpresss thrpt 5 4403695.596 ± 113498.704 ops/s
Beetl.reflect thrpt 5 83723.859 ± 40897.270 ops/s
Beetl.simpleExpress thrpt 5 4386398.540 ± 111306.217 ops/s
Groovy.ifExpresss thrpt 5 303806.258 ± 12134.866 ops/s
Groovy.simpleExpress thrpt 5 302431.969 ± 8039.171 ops/s
Jexl3.forExpresss thrpt 5 747716.738 ± 25959.630 ops/s
Jexl3.ifExpresss thrpt 5 3806159.078 ± 99125.411 ops/s
Jexl3.simpleExpress thrpt 5 3413623.305 ± 56783.177 ops/s
JfireEL.ifExpresss thrpt 5 34195894.961 ± 357271.824 ops/s
JfireEL.simpleExpress thrpt 5 24998273.343 ± 2685584.807 ops/s
Liquor.forExpresss thrpt 5 195481886.461 ± 2464897.556 ops/s
Liquor.ifExpresss thrpt 5 205435909.028 ± 5286307.686 ops/s
Liquor.simpleExpress thrpt 5 200625386.760 ± 2214530.143 ops/s
Mvel.forExpresss thrpt 5 4415.331 ± 60.968 ops/s
Mvel.ifExpresss thrpt 5 184213.448 ± 58112.716 ops/s
Mvel.simpleExpress thrpt 5 253283.417 ± 42492.561 ops/s
Nashorn.ifExpresss thrpt 5 13056.037 ± 2274.430 ops/s
Nashorn.simpleExpress thrpt 5 12543.251 ± 1230.481 ops/s
Spel.ifExpresss thrpt 5 19045225.353 ± 300079.309 ops/s
Spel.simpleExpress thrpt 5 18670957.394 ± 203441.671 ops/s
WastEl.forExpresss thrpt 5 702537069.120 ± 1918356.393 ops/s
WastEl.ifExpresss thrpt 5 1102947933.898 ± 11004950.388 ops/s
WastEl.simpleExpress thrpt 5 626007123.964 ± 14879444.442 ops/s
对结果有质疑的或者有感兴趣的也可以自己把代码拉下来试试
WastEl文档地址
源码地址
- gitee: https://gitee.com/xiaoch0209/wast
- github: https://github.com/wycst/wast