【请教】a.b.c语法糖性能问题
前提:业务上允许a.b.c中a or b为null,当a or b为null时返回null,且为了方便配置大部分均这样配置 Option设置:Options.NIL_WHEN_PROPERTY_NOT_FOUND=true
性能分析时,发现com.googlecode.aviator.utils.Reflector#fastGetProperty(java.lang.String, java.lang.String[], java.util.Map<java.lang.String,java.lang.Object>, com.googlecode.aviator.utils.Reflector.Target, boolean, int, int)方法中有如下实现
通过火焰图分析发现com.googlecode.aviator.runtime.type.AviatorJavaType#tryResolveAsClass方法执行性能损耗极大(如下面的性能分析所示)。
分析该方法的实现逻辑,大概是:当a.b.c中a为null时,对a进行一系列的class类型处理,其目的之一是读取静态变量的前置逻辑。 除此之外该方法还有哪些意图? 如果禁止该方法的执行会丢失哪些功能? 提供禁止执行的选项开关(如添加Options选项)是否是一种解决方案?
附:性能对比实现与结果 实现:
- 对com.googlecode.aviator.runtime.type.AviatorJavaType#tryResolveAsClass执行添加开关Options.SWITCH
if (target.innerEnv != null) {
val = target.innerEnv.get(rName);
if (val == null && i == 0 && env instanceof Env && RuntimeUtils.getInstance(env).getOptionValue(Options.SWITCH).bool) {
val = AviatorJavaType.tryResolveAsClass(env, rName);
}
} else {
val = fastGetProperty(target.targetObject, rName, PropertyType.Getter);
}
- 性能测试单元
package com.googlecode.aviator;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class FastGetPropertyTest {
static Map env;
static ExecutorService BEFORE_OPTIMIZE_EXECUTOR = Executors.newFixedThreadPool(5);
static AviatorEvaluatorInstance beforeOptimizeInstance;
static Expression beforeOptimizeExpression;
static ExecutorService AFTER_OPTIMIZE_EXECUTOR = Executors.newFixedThreadPool(5);
static AviatorEvaluatorInstance afterOptimizeInstance;
static Expression afterOptimizeExpression;
static {
beforeOptimizeInstance = AviatorEvaluator.newInstance();
beforeOptimizeInstance.setOption(Options.NIL_WHEN_PROPERTY_NOT_FOUND, true);
beforeOptimizeExpression = beforeOptimizeInstance.compile("a.b.c", true);
afterOptimizeInstance = AviatorEvaluator.newInstance();
afterOptimizeInstance.setOption(Options.NIL_WHEN_PROPERTY_NOT_FOUND, true);
afterOptimizeInstance.setOption(Options.SWITCH, false);
afterOptimizeExpression = afterOptimizeInstance.compile("a.b.c", true);
Map env = new HashMap();
Map a = new HashMap();
a.put("c", "c");
env.put("b", a);
}
public static void main(String[] args) {
// 优化前
for (int i = 0; i < 100000; i++) {
BEFORE_OPTIMIZE_EXECUTOR.submit(new Runnable() {
@Override
public void run() {
beforeOptimizeExpression.execute(env);
}
});
}
// 优化后
for (int i = 0; i < 100000; i++) {
AFTER_OPTIMIZE_EXECUTOR.submit(new Runnable() {
@Override
public void run() {
afterOptimizeExpression.execute(env);
}
});
}
BEFORE_OPTIMIZE_EXECUTOR.shutdown();
AFTER_OPTIMIZE_EXECUTOR.shutdown();
}
}
结论:
- 优化前
- 优化后
@JoabYang 收到,感谢您的反馈。我研究下。
或者扩展语法,能否支持类似前端React的写法,让空字符串也能跑 "#foo?.bbb ==nil ? 1 : 2"