Skip to content

【请教】a.b.c语法糖性能问题 #529

Description

@JoabYang

前提:业务上允许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)方法中有如下实现
image
通过火焰图分析发现com.googlecode.aviator.runtime.type.AviatorJavaType#tryResolveAsClass方法执行性能损耗极大(如下面的性能分析所示)。

分析该方法的实现逻辑,大概是:当a.b.c中a为null时,对a进行一系列的class类型处理,其目的之一是读取静态变量的前置逻辑。
除此之外该方法还有哪些意图?
如果禁止该方法的执行会丢失哪些功能?
提供禁止执行的选项开关(如添加Options选项)是否是一种解决方案?

附:性能对比实现与结果
实现:

  1. 对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);
}
  1. 性能测试单元
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();
  }
}

结论:

  1. 优化前

image

2. 优化后

image

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions