目录
1 collection 数据场景性能对比
场景示例:满足 categoryIdSet.contains(categoryId) 的条件。下面会根据这个表达式设计测试方案。
1.1 测试场景说明
这里以实际性能测试的方法名作为场景代号。
1.1.1 Java 代码执行场景
-
executeWithoutExpression:不用表达式,直接运行 Java 代码
1.1.2 aviator 场景
-
场景特性对比
场景代号 |
是否编译 |
是否预编译 |
编译结果是否缓存 |
---|---|---|---|
aviatorValidate |
N |
N |
N |
aviatorValidateWithPreviewCachedCompile |
Y |
Y |
Y |
aviatorValidateWithCachedCompile |
Y |
N |
Y |
-
场景特性详细说明
-
编译:调用 aviator 的 compile 方法,将表达式编译成字节码
-
预编译(线程安全):全局生成唯一一个编译后的对象,每次执行表达式的时候复用这个编译后的对象。因为实际业务场景下表达式是基本不变的,所以在可穷举的情况下,预先可以做好 aviator 的编译,后面需要变更的只是变量的值而已。
-
缓存编译结果: aviator 支持缓存编译结果,这样如果每次解析的表达式相同的时候,则可以从全局缓存中获取。另外提一下,这个缓存采用的是 LRU 淘汰策略。
-
1.1.3 spel 场景
-
场景特性对比
场景代号 |
是否引入上下文 |
是否引入数据对象 |
是否提前生成解析器 |
是否通过数据对象执行业务逻辑 |
---|---|---|---|---|
spelValidateWithContext |
Y |
N |
N |
N |
spelValidate |
N |
Y |
N |
N |
spelValidateWithInnerFunction |
N |
Y |
N |
Y |
spelValidateWithInnerFunctionAndContext |
Y |
Y |
N |
Y |
spelValidateWithInnerFunctionAndContextAndPreviewNewInstance |
Y |
Y |
Y |
Y |
-
场景特性详细说明
-
上下文:spel 支持直接解析 root object,也支持通过 context 来添加变量,用来构建表达式的执行环境
-
数据对象:即 root object,包括执行业务逻辑的全部变量
-
提前生成解析器:全局唯一一个 spel 解析器和上下文,每次执行表达式的时候都复用这个解析器和上下文,只需要修改数据即可
-
通过数据对象执行业务逻辑:表达式不关心业务逻辑,业务逻辑交给 root object 中的方法来实现,表达式只管调用 root object 中的方法
-
1.2 测试数据生成规则
-
规则集合:在 0~10w 之间随机生成 1w 个数
-
需要匹配的数值:在 0~10w 之间随机生成
package rule.function.collection;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import lombok.Data;
import java.util.List;
import java.util.Set;
/**
* @author lihaike
* @date 2021/1/21
*/
@Data
public class CollectionExpressionData {
private Set<Long> allCategoryIdSet;
private List<Long> categoryIdSet;
public void init(int testCount) {
categoryIdSet = Lists.newArrayList();
allCategoryIdSet = Sets.newHashSet();
// 总集合设置为子集合的 10 倍
int allCount = 10000;
int allNumber = 10 * allCount;
for (int i = 0; i < testCount; i++) {
categoryIdSet.add((long) (Math.random() * allNumber));
}
for (int i = 0; i < allCount; i++) {
allCategoryIdSet.add((long) (Math.random() * allN