表达式引擎性能对比

1. 表达式引擎选型

如果要做一个规则引擎,需要匹配一组规则集来做决策,此时就需要一个表达式引擎来辅助。
选择 5 种表达式引擎进行性能对比,从而选择最优表达式引擎和最优方案。Janino、QLExpress、MEVL、JUEL、FEL。
当然,除了计算性能,还要考虑是否满足功能,以及是否有安全漏洞等,本文仅进行表达式引擎的性能对比。

2. 性能测试

2.1 测试维度

  1. 表达式维度:主要采用了3种表达式,表达式的语法在不同的表达式引擎中也不同,详见3.2 。
  • 表达式1: 最常见的场景(多个条件进行and操作):city.equals(‘杭州’) && age<=20
  • 表达式2: 包含特殊的操作(contains):city.equals(‘杭州’) && age<=20 && stringList.contains(str)
  • 表达式3: 一个稍微复杂一点的语法树 :a>1 && ((b>1 || c<1) || (a>1 && b<1 && c>1))
  1. 数据量
  • 1000万
  • 2000万
  • 4000万

2.2 测试方式

根据数据量执行多少次 for 循环,记录下表达式计算的总耗时,单位毫秒 (ms)。为了保证一定的差异性,变量赋值的时候,采用变化的值。代码详见 3.2 。

2.3 结论

  • 表达式1:city.equals(“杭州”) && age<=20
Janino QL Mvel (预编译) Juel Fel
1000万 583 6885 2634 3174 125065
2000万 1171 11363 4167 4318 277257
4000万 1951 22979 8544 9117 519036
  • 表达式2: city.equals(“杭州”) && age<=20 && stringList.contains(str)
Janino QL Mvel (预编译) Juel Fel
1000万 508 6473 2810 2787 166865
2000万 983 12793 4627 5728 339085
4000万 2008 25595 9656 11417 670728
  • 表达式3:a>1 && ((b>1 || c<1) || (a>1 && b<1 && c>1))
Janino QL Mvel (预编译) Juel Fel
1000万 489 3082 2206 3056 167739
2000万 947 6156 3445 5950 321651
4000万 1909 12353 7284 12934 642368

Janino 表达式引擎的性能最优。
处理速度上,Janino > Mvel(预编译) > Juel > QL > Fel 。

3. 附录

3.1 机器配置

本机 Mac 配置:
MacBook Pro (13-inch, 2019, Four Thunderbolt 3 ports)
处理器 2.4 GHz 四核Intel Core i5
内存 16 GB 2133 MHz LPDDR3
图形卡 Intel Iris Plus Graphics 655 1536 MB

3.2 Java 测试代码

  • Janino
import org.codehaus.commons.compiler.CompilerFactoryFactory;
import org.codehaus.commons.compiler.IExpressionEvaluator;
import org.junit.Test;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

/**
 * Description:
 *
 * @author mwt
 * @version 1.0
 * @date 2020/5/21
 */
public class JaninoExpressionTest {

    @Test
    public void test1() throws Exception {
        String ruleExpress = "city.equals(\"杭州\") && age<=20";

        long count1 = 1000 * 10000;
        System.out.println("\nJaninoExpression1 数据量 1000 万:");
        execute(count1, ruleExpress);

        long count2 = 2000 * 10000;
        System.out.println("\nJaninoExpression1 数据量 2000 万:");
        execute(count2, ruleExpress);

        long count3 = 4000 * 10000;
        System.out.println("\nJaninoExpression1 数据量 4000 万:");
        execute(count3, ruleExpress);
    }


    @Test
    public void test2() throws Exception {
        String ruleExpress = "city.equals(\"杭州\") && age<=20 && stringList.contains(str)";

        long count1 = 1000 * 10000;
        System.out.println("\nJaninoExpression2 数据量 1000 万:");
        execute(count1, ruleExpress);

        long count2 = 2000 * 10000;
        System.out.println("\nJaninoExpression2 数据量 2000 万:");
        execute(count2, ruleExpress);

        long count3 = 4000 * 10000;
        System.out.println("\nJaninoExpression2 数据量 4000 万:");
        execute(count3, ruleExpress);

    }

    @Test
    public void test3() throws Exception {
        String ruleExpress = "a>1 && ((b>1 || c<1) || (a>1 && b<1 && c>1))";

        long count1 = 1000 * 10000;
        System.out.println("\nJaninoExpression3 数据量 1000 万:");
        execute(count1, ruleExpress);

        long count2 = 2000 * 10000;
        System.out.println("\nJaninoExpression3 数据量 2000 万:");
        execute(count2, ruleExpress);

        long count3 = 4000 * 10000;
        System.out.println("\nJaninoExpression3 数据量 4000 万:");
        execute(count3, ruleExpress);
    }

    private void execute(long count, String expression) throws Exception {
        IExpressionEvaluator expressionEvaluator =
                CompilerFactoryFactory.getDefaultCompilerFactory().newExpressionEvaluator();
        expressionEvaluator.setExpressionType(boolean.class);
        expressionEvaluator.setParameters(
                new String[]{"city", "age", "stringList", "str", "a", "b", "c"},
                new Class[]{String.class, Integer.class, List.class, String.class,
                        Integer.class, Integer.class, Integer.class}
        );
        expressionEvaluator.cook(expression);

        long start = System.currentTimeMillis();
        List<String> stringList = new ArrayList<String>(2);
        stringList.add("hello");
        stringList.add("world");
        Random random = new Random();
        for (int i = 0; i < count; i++) {
            Object[] arguments = new Object[7];
            int age = random.nextInt(50);
            if (i % 2 == 0) {
                arguments[0] = "杭州";
            } else {
                arguments[0] = "北京";

            }
            arguments[1] = age;
            arguments[2] = stringList;
            if (i % 3 == 0) {
                arguments[3] = "hello";
            } else if (i % 3 == 1) {
                arguments[3] = "world";
            } else {
                arguments[3] = "anything";
            }
            arguments[4] = random.nextInt(2);
            arguments[5] = random.nextInt(2);
            arguments[6] = random.nextInt(2);

            Object res = expressionEvaluator.evaluate(arguments);
        }
        long end = System.currentTimeMillis();
        long intervalInMs = end - start;
        float avg = (float) count / intervalInMs * 1000;

        System.out.println("总耗时毫秒:" + intervalInMs);
        System.out.println("每秒处理条数:" + avg);
    }
}
  • QL
import com.ql.util.express.DefaultContext;
import com.ql.util.express.ExpressRunner;
import org.junit.Test;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

/**
 * Description:
 *
 * @author mwt
 * @version 1.0
 * @date 2020/5/21
 */
public class QLExpressTest {

    @Test
    public void test1() throws Exception {
        String ruleExpress = "city.equals(\"杭州\") && age<=20";

        long count1 = 1000 * 10000;
        System.out.println("\nQLExpress1 数据量 1000 万:");
        execute(count1, ruleExpress);

        long count2 = 2000 * 10000;
        System.out.println("\nQLExpress1 数据量 2000 万:");
        execute(count2, ruleExpress);

        long count3 = 4000 * 10000;
        System.out.println("\nQLExpress1 数据量 4000 万:");
        execute(count3, ruleExpress);
    }


    @Test
    public void test2() throws Exception {
        String ruleExpress = "city.equals(\"杭州\") && age<=20 && stringList.contains(str)";

        long count1 = 1000 * 10000;
        System.out.println("\nQLExpress2 数据量 1000 万:");
        execute(count1, ruleExpress);

        long count2 = 2000 * 10000;
        System.out.println("\nQLExpress2 数据量 2000 万:");
        execute(count2, ruleExpress);

        long count3 = 4000 * 10000;
        System.out.println("\nQLExpress2 数据量 4000 万:");
        execute(count3, ruleExpress);

    }

    @Test
    public void test3() throws Exception {
        String ruleExpress = "a>1 && ((b>1 || c<1) || (a>1 && b<1 && c>1))";

        long count1 = 1000 * 10000;
        System.out.println("\nQLExpress3 数据量 1000 万:");
        execute(count1, ruleExpress);

        long count2 = 2000 * 10000;
        System.out.println("\nQLExpress3 数据量 2000 万:");
        execute(count2, ruleExpress);

        long count3 = 4000 * 10000;
        System.out.println("\nQLExpress3 数据量 4000 万:");
        execute(count3, ruleExpress);
    }


    private void execute(long count, String expression) throws Exception {
        ExpressRunner runner = new ExpressRunner();
        DefaultContext<String, Object> context = new DefaultContext<String, Object>();

        long start = System.currentTimeMillis();
        List<String> stringList = new ArrayList<String>(2);
        stringList.add("hello");
        stringList.add("world");
        Random random = new Random();
        for (int i = 0; i < count; i++) {
            int age = random.nextInt(50);
            if (i % 2 == 0) {
                context.put("city", "杭州");
            } else {
                context.put("city", "北京");
            }
            context.put("age", age);
            context.put("stringList", stringList);
            if (i % 3 == 0) {
                context.put("str", "hello");
            } else if (i % 3 == 1) {
                context.put("str", "world");

            } else {
                context.put("str", "anything");
            }
            context.put("a",random.nextInt(2));
            context.put("b",random.nextInt(2));
            context.put("c",random.nextInt(2));

            Object res = runner.execute(expression, context, null, true, false);

        }
        long end = System.currentTimeMillis();
        long intervalInMs = end - start;
        float avg = (float) count / intervalInMs * 1000;

        System.out.println("总耗时毫秒:" + intervalInMs);
        System.out.println("每秒处理条数:" + avg);
    }
}
  • Mvel
import org.junit.Test;
import org.mvel2.MVEL;
import org.mvel2.ParserContext;

import java.io.Serializable;
import java.util.*;

/**
 * Description:
 *
 * @author mwt
 * @version 1.0
 * @date 2020/5/22
 */
public class MvelExpressTest {

    // =========================== mvel 不编译,超级慢 ===========================
    @Test
    public void test11() {
        String ruleExpress = "city=='杭州' && age<=20";

        long count1 = 1000 * 10000;
        System.out.println("\nMvelCompileExpress1 数据量 1000 万:");
        execute1(count1, ruleExpress);

        long count2 = 2000 * 10000;
        System.out.println("\nMvelCompileExpress1 数据量 2000 万:");
        execute1(count2, ruleExpress);

        long count3 = 4000 * 10000;
        System.out.println("\nMvelCompileExpress1 数据量 4000 万:");
        execute1(count3, ruleExpress);
    }


    @Test
    public void test12() {
        String ruleExpress = "city=='杭州' && age<=20 && stringList.contains(str)";

        long count1 = 1000 * 10000;
        System.out.println("\nMvelCompileExpress2 数据量 1000 万:");
        execute1(count1, ruleExpress);

        long count2 = 2000 * 10000;
        System.out.println("\nMvelCompileExpress2 数据量 2000 万:");
        execute1(count2, ruleExpress);

        long count3 = 4000 * 10000;
        System.out.println("\nMvelCompileExpress2 数据量 4000 万:");
        execute1(count3, ruleExpress);

    }

    @Test
    public void test13() {
        String ruleExpress = "a>1 && ((b>1 || c<1) || (a>1 && b<1 && c>1))";

        long count1 = 1000 * 10000;
        System.out.println("\nMvelCompileExpress3 数据量 1000 万:");
        execute1(count1, ruleExpress);

        long count2 = 2000 * 10000;
        System.out.println("\nMvelCompileExpress3 数据量 2000 万:");
        execute1(count2, ruleExpress);

        long count3 = 4000 * 10000;
        System.out.println("\nMvelCompileExpress3 数据量 4000 万:");
        execute1(count3, ruleExpress);
    }


    // =========================== mvel 先编译 ===========================
    @Test
    public void test21() {
        String ruleExpress = "city=='杭州' && age<=20";

        long count1 = 1000 * 10000;
        System.out.println("\nMvelCompileExpress1 数据量 1000 万:");
        execute2(count1, ruleExpress);

        long count2 = 2000 * 10000;
        System.out.println("\nMvelCompileExpress1 数据量 2000 万:");
        execute2(count2, ruleExpress);

        long count3 = 4000 * 10000;
        System.out.println("\nMvelCompileExpress1 数据量 4000 万:");
        execute2(count3, ruleExpress);
    }


    @Test
    public void test22() {
        String ruleExpress = "city=='杭州' && age<=20 && stringList.contains(str)";

        long count1 = 1000 * 10000;
        System.out.println("\nMvelCompileExpress2 数据量 1000 万:");
        execute2(count1, ruleExpress);

        long count2 = 2000 * 10000;
        System.out.println("\nMvelCompileExpress2 数据量 2000 万:");
        execute2(count2, ruleExpress);

        long count3 = 4000 * 10000;
        System.out.println("\nMvelCompileExpress2 数据量 4000 万:");
        execute2(count3, ruleExpress);

    }

    @Test
    public void test23() {
        String ruleExpress = "a>1 && ((b>1 || c<1) || (a>1 && b<1 && c>1))";

        long count1 = 1000 * 10000;
        System.out.println("\nMvelCompileExpress3 数据量 1000 万:");
        execute2(count1, ruleExpress);

        long count2 = 2000 * 10000;
        System.out.println("\nMvelCompileExpress3 数据量 2000 万:");
        execute2(count2, ruleExpress);

        long count3 = 4000 * 10000;
        System.out.println("\nMvelCompileExpress3 数据量 4000 万:");
        execute2(count3, ruleExpress);
    }

    // =========================== mvel 先编译,且输入值类型指定 ===========================
    @Test
    public void test31() {
        String ruleExpress = "city=='杭州' && age<=20";

        long count1 = 1000 * 10000;
        System.out.println("\nMvelCompileExpress1 数据量 1000 万:");
        execute3(count1, ruleExpress);

        long count2 = 2000 * 10000;
        System.out.println("\nMvelCompileExpress1 数据量 2000 万:");
        execute3(count2, ruleExpress);

        long count3 = 4000 * 10000;
        System.out.println("\nMvelCompileExpress1 数据量 4000 万:");
        execute3(count3, ruleExpress);
    }


    @Test
    public void test32() {
        String ruleExpress = "city=='杭州' && age<=20 && stringList.contains(str)";

        long count1 = 1000 * 10000;
        System.out.println("\nMvelCompileExpress2 数据量 1000 万:");
        execute3(count1, ruleExpress);

        long count2 = 2000 * 10000;
        System.out.println("\nMvelCompileExpress2 数据量 2000 万:");
        execute3(count2, ruleExpress);

        long count3 = 4000 * 10000;
        System.out.println("\nMvelCompileExpress2 数据量 4000 万:");
        execute3(count3, ruleExpress);

    }

    @Test
    public void test33() {
        String ruleExpress = "a>1 && ((b>1 || c<1) || (a>1 && b<1 && c>1))";

        long count1 = 1000 * 10000;
        System.out.println("\nMvelCompileExpress3 数据量 1000 万:");
        execute3(count1, ruleExpress);

        long count2 = 2000 * 10000;
        System.out.println("\nMvelCompileExpress3 数据量 2000 万:");
        execute3(count2, ruleExpress);

        long count3 = 4000 * 10000;
        System.out.println("\nMvelCompileExpress3 数据量 4000 万:");
        execute3(count3, ruleExpress);
    }

    /**
     * mvel 不编译
     */
    private void execute1(long count, String expression) {

        long start = System.currentTimeMillis();
        Map<String, Object> paramMap = new HashMap<String, Object>();
        List<String> stringList = new ArrayList<String>(2);
        stringList.add("hello");
        stringList.add("world");
        Random random = new Random();
        for (int i = 0; i < count; i++) {
            int age = random.nextInt(50);
            if (i % 2 == 0) {
                paramMap.put("city", "杭州");
            } else {
                paramMap.put("city", "北京");
            }
            paramMap.put("age", age);
            paramMap.put("stringList", stringList);
            if (i % 3 == 0) {
                paramMap.put("str", "hello");
            } else if (i % 3 == 1) {
                paramMap.put("str", "world");

            } else {
                paramMap.put("str", "anything");
            }
            paramMap.put("a", random.nextInt(2));
            paramMap.put("b", random.nextInt(2));
            paramMap.put("c", random.nextInt(2));

            Object res = MVEL.eval(expression, paramMap);

        }
        long end = System.currentTimeMillis();
        long intervalInMs = end - start;
        float avg = (float) count / intervalInMs * 1000;

        System.out.println("总耗时毫秒:" + intervalInMs);
        System.out.println("每秒处理条数:" + avg);
    }


    /**
     * mvel 先编译
     */
    private void execute2(long count, String expression) {

        long start = System.currentTimeMillis();
        Serializable serializable = MVEL.compileExpression(expression);
        Map<String, Object> paramMap = new HashMap<String, Object>();
        List<String> stringList = new ArrayList<String>(2);
        stringList.add("hello");
        stringList.add("world");
        Random random = new Random();
        for (int i = 0; i < count; i++) {
            int age = random.nextInt(50);
            if (i % 2 == 0) {
                paramMap.put("city", "杭州");
            } else {
                paramMap.put("city", "北京");
            }
            paramMap.put("age", age);
            paramMap.put("stringList", stringList);
            if (i % 3 == 0) {
                paramMap.put("str", "hello");
            } else if (i % 3 == 1) {
                paramMap.put("str", "world");

            } else {
                paramMap.put("str", "anything");
            }
            paramMap.put("a", random.nextInt(2));
            paramMap.put("b", random.nextInt(2));
            paramMap.put("c", random.nextInt(2));

            Object res = MVEL.executeExpression(serializable, paramMap);

        }
        long end = System.currentTimeMillis();
        long intervalInMs = end - start;
        float avg = (float) count / intervalInMs * 1000;

        System.out.println("总耗时毫秒:" + intervalInMs);
        System.out.println("每秒处理条数:" + avg);
    }

    /**
     * mvel 先编译,且输入值类型指定
     */
    private void execute3(long count, String expression) {

        long start = System.currentTimeMillis();
        ParserContext context = ParserContext.create();
        context.addInput("city", String.class);
        context.addInput("age", Integer.class);
        context.addInput("stringList", List.class);
        context.addInput("str", String.class);
        context.addInput("a", Integer.class);
        context.addInput("b", Integer.class);
        context.addInput("c", Integer.class);

        Serializable serializable = MVEL.compileExpression(expression);
        Map<String, Object> paramMap = new HashMap<String, Object>();
        List<String> stringList = new ArrayList<String>(2);
        stringList.add("hello");
        stringList.add("world");
        Random random = new Random();
        for (int i = 0; i < count; i++) {
            int age = random.nextInt(50);
            if (i % 2 == 0) {
                paramMap.put("city", "杭州");
            } else {
                paramMap.put("city", "北京");
            }
            paramMap.put("age", age);
            paramMap.put("stringList", stringList);
            if (i % 3 == 0) {
                paramMap.put("str", "hello");
            } else if (i % 3 == 1) {
                paramMap.put("str", "world");

            } else {
                paramMap.put("str", "anything");
            }
            paramMap.put("a", random.nextInt(2));
            paramMap.put("b", random.nextInt(2));
            paramMap.put("c", random.nextInt(2));

            Object res = MVEL.executeExpression(serializable, paramMap);

        }
        long end = System.currentTimeMillis();
        long intervalInMs = end - start;
        float avg = (float) count / intervalInMs * 1000;

        System.out.println("总耗时毫秒:" + intervalInMs);
        System.out.println("每秒处理条数:" + avg);
    }
}
  • Juel
import de.odysseus.el.ExpressionFactoryImpl;
import de.odysseus.el.util.SimpleContext;
import org.junit.Test;

import javax.el.ExpressionFactory;
import javax.el.ValueExpression;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

/**
 * Description:
 *
 * @author mwt
 * @version 1.0
 * @date 2020/5/22
 */
public class JuelExpressTest {

    @Test
    public void test1()   {
        String ruleExpress = "city.equals(\"杭州\") && age<=20";

        long count1 = 1000 * 10000;
        System.out.println("\nJuelExpress1 数据量 1000 万:");
        execute(count1, ruleExpress);

        long count2 = 2000 * 10000;
        System.out.println("\nJuelExpress1 数据量 2000 万:");
        execute(count2, ruleExpress);

        long count3 = 4000 * 10000;
        System.out.println("\nJuelExpress1 数据量 4000 万:");
        execute(count3, ruleExpress);
    }


    @Test
    public void test2()   {
        String ruleExpress = "city.equals(\"杭州\") && age<=20 && stringList.contains(str)";

        long count1 = 1000 * 10000;
        System.out.println("\nJuelExpress2 数据量 1000 万:");
        execute(count1, ruleExpress);

        long count2 = 2000 * 10000;
        System.out.println("\nJuelExpress2 数据量 2000 万:");
        execute(count2, ruleExpress);

        long count3 = 4000 * 10000;
        System.out.println("\nJuelExpress2 数据量 4000 万:");
        execute(count3, ruleExpress);

    }

    @Test
    public void test3()   {
        String ruleExpress = "a>1 && ((b>1 || c<1) || (a>1 && b<1 && c>1))";

        long count1 = 1000 * 10000;
        System.out.println("\nJuelExpress3 数据量 1000 万:");
        execute(count1, ruleExpress);

        long count2 = 2000 * 10000;
        System.out.println("\nJuelExpress3 数据量 2000 万:");
        execute(count2, ruleExpress);

        long count3 = 4000 * 10000;
        System.out.println("\nJuelExpress3 数据量 4000 万:");
        execute(count3, ruleExpress);
    }


    private void execute(long count, String expression)  {

        ExpressionFactory factory = new ExpressionFactoryImpl();
        long start = System.currentTimeMillis();
        List<String> stringList = new ArrayList<String>(2);
        stringList.add("hello");
        stringList.add("world");
        Random random = new Random();
        for (int i = 0; i < count; i++) {
            SimpleContext context = new SimpleContext();

            int age = random.nextInt(50);
            if (i % 2 == 0) {
                context.setVariable("city", factory.createValueExpression("杭州", String.class));
            } else {
                context.setVariable("city", factory.createValueExpression("北京", String.class));
            }
            context.setVariable("age", factory.createValueExpression(age, Integer.class));
            context.setVariable("stringList", factory.createValueExpression(stringList, List.class));

            if (i % 3 == 0) {
                context.setVariable("str", factory.createValueExpression("hello", String.class));
            } else if (i % 3 == 1) {
                context.setVariable("str", factory.createValueExpression("world", String.class));
            } else {
                context.setVariable("str", factory.createValueExpression("anything", String.class));
            }
            context.setVariable("a", factory.createValueExpression(random.nextInt(2), Integer.class));
            context.setVariable("b", factory.createValueExpression(random.nextInt(2), Integer.class));
            context.setVariable("c", factory.createValueExpression(random.nextInt(2), Integer.class));

            ValueExpression e = factory.createValueExpression(context, "${" + expression + "}", Boolean.class);

        }
        long end = System.currentTimeMillis();
        long intervalInMs = end - start;
        float avg = (float) count / intervalInMs * 1000;

        System.out.println("总耗时毫秒:" + intervalInMs);
        System.out.println("每秒处理条数:" + avg);
    }
}
  • Fel
import com.greenpineyu.fel.FelEngine;
import com.greenpineyu.fel.FelEngineImpl;
import com.greenpineyu.fel.context.FelContext;
import org.junit.Test;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

/**
 * Description:
 *
 * @author mwt
 * @version 1.0
 * @date 2020/5/22
 */
public class FelExpressTest {

    @Test
    public void test1() {
        String ruleExpress = "city.equals(\"杭州\") && age<=20";

        long count1 = 1000 * 10000;
        System.out.println("\nFelExpress1 数据量 1000 万:");
        execute(count1, ruleExpress);

        long count2 = 2000 * 10000;
        System.out.println("\nFelExpress1 数据量 2000 万:");
        execute(count2, ruleExpress);

        long count3 = 4000 * 10000;
        System.out.println("\nFelExpress1 数据量 4000 万:");
        execute(count3, ruleExpress);
    }


    @Test
    public void test2() {
        String ruleExpress = "city.equals(\"杭州\") && age<=20 && stringList.contains(str)";

        long count1 = 1000 * 10000;
        System.out.println("\nFelExpress2 数据量 1000 万:");
        execute(count1, ruleExpress);

        long count2 = 2000 * 10000;
        System.out.println("\nFelExpress2 数据量 2000 万:");
        execute(count2, ruleExpress);

        long count3 = 4000 * 10000;
        System.out.println("\nFelExpress2 数据量 4000 万:");
        execute(count3, ruleExpress);

    }

    @Test
    public void test3() {
        String ruleExpress = "a>1 && ((b>1 || c<1) || (a>1 && b<1 && c>1))";

        long count1 = 1000 * 10000;
        System.out.println("\nFelExpress3 数据量 1000 万:");
        execute(count1, ruleExpress);

        long count2 = 2000 * 10000;
        System.out.println("\nFelExpress3 数据量 2000 万:");
        execute(count2, ruleExpress);

        long count3 = 4000 * 10000;
        System.out.println("\nFelExpress3 数据量 4000 万:");
        execute(count3, ruleExpress);
    }


    private void execute(long count, String expression) {

        FelEngine fel = new FelEngineImpl();
        FelContext context = fel.getContext();

        long start = System.currentTimeMillis();
        List<String> stringList = new ArrayList<String>(2);
        stringList.add("hello");
        stringList.add("world");
        Random random = new Random();
        for (int i = 0; i < count; i++) {
            int age = random.nextInt(50);
            if (i % 2 == 0) {
                context.set("city", "杭州");
            } else {
                context.set("city", "北京");
            }
            context.set("age", age);
            context.set("stringList", stringList);
            if (i % 3 == 0) {
                context.set("str", "hello");
            } else if (i % 3 == 1) {
                context.set("str", "world");

            } else {
                context.set("str", "anything");
            }
            context.set("a", random.nextInt(2));
            context.set("b", random.nextInt(2));
            context.set("c", random.nextInt(2));

            Object res = fel.eval(expression, context);
            System.out.println(res);

        }
        long end = System.currentTimeMillis();
        long intervalInMs = end - start;
        float avg = (float) count / intervalInMs * 1000;

        System.out.println("总耗时毫秒:" + intervalInMs);
        System.out.println("每秒处理条数:" + avg);
    }
}

参考:
http://www.datadriven.top/2018/02/03/%E8%A1%A8%E8%BE%BE%E5%BC%8F%E5%BC%95%E6%93%8E%E6%80%A7%E8%83%BD%E6%AF%94%E8%BE%83/index.html
http://www.welkinbai.com/2019/05/30/ql-intro/#1-%E4%BE%9D%E8%B5%96%E5%92%8C%E5%9F%BA%E6%9C%AC%E8%B0%83%E7%94%A8-1
https://bigjun2017.github.io/2018/09/18/hou-duan/java/mvel2.x-yu-fa-zhi-nan/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章