跳到主要内容

实例

caution

请记住,ActiveJ Specializer是一个实验性项目,请谨慎使用它。 它不支持lambda表达式,而且在专门处理非琐碎的实例时可能会有困难。

简单的计算器#

我们把这个 Parsec计算器的教程 ,并为ActiveJ Specializer做了一些调整。 在最初的教程中,Parsec将解析的表达式返回为双倍值。

解析器<Double> parser = new OperatorTable<Double>()    .infixl(op(" ", (l, r) -> l r), 10)    .infixl(op("-", (l, r) -> l - r), 10)    .infixl(Parsers.or(term("*"), WHITESPACE_MUL).retn((l, r) -> l * r), 20)    .infixl(op("/", (l, r) -> l / r), 20)    .prefix(op("-", v -> -v), 30)    .building(unit) 。

ActiveJ Specializer在树状数据结构方面显示了它的优势。 所以我们将把表达式解析为AST。

private static final Parser<CalculatorExpression> EXPRESSION = new OperatorTable<CalculatorExpression>()        .infixl(DELIMITERS.token("+").retn(Sum::new), 10)        .infixl(DELIMITERS.token("-").retn(Sub::new), 10)        .infixl(DELIMITERS.token("*").retn(Mul::new), 20)        .infixl(DELIMITERS.token("/").retn(Div::new), 20)        .infixl(DELIMITERS.token("%").retn(Mod::new), 20)        .prefix(DELIMITERS.token("-").retn(Neg::new), 30)        .infixr(DELIMITERS.token("^").retn(Pow::new), 40)        .build(ATOM);

假设我们有一个简单的方程式 3 2 * 4。 根据解析器,将创建以下AST。

graph TD + --> 3 + --> * * --> 2 * --> 4

让我们测试一下Specializer。

public static void main(String[] args) {  double x = -1;
  // manual code, super fast  System.out.println(((2.0 + 2.0 * 2.0) * -x) + 5.0 + 1024.0 / (100.0 + 58.0) * 50.0 * 37.0 - 100.0 + 2.0 * (Math.pow(x, 2.0)) % 3.0);
  CalculatorExpression expression = PARSER.parse("((2 + 2 * 2) * -x) + 5 + 1024 / (100 + 58) * 50 * 37 - 100 + 2 * x ^ 2 % 3");
  System.out.println(expression);
  // tree-walking evaluation, super slow  System.out.println(expression.evaluate(x));
  // specialized instance evaluation, about as fast as manual code  CalculatorExpression specialized = SPECIALIZER.specialize(expression);  System.out.println(specialized.evaluate(x));}

ActiveJ Specializer将AST转化为一组静态的最终类,并将所提供的 方程的值烘烤出来。 JIT在运行时对这些类进行了大量的优化和内联。 因此,我们收到了一个优化的表达式 实例,在我们多次计算一个未知值的方程时可以重复使用。 是时候进行一些基准测试了。 让我们尝试以三种不同的方式处理方程 (2+ 2 * 2) * -x) + 5 + 1024 / (100 + 58) * 50 * 37 - 100 + 2 * x ^2 % 3 并比较性能: 手动输入方程 解析方程并评估它 无专业化 * 解析方程并评价它 专业化 基准的结果很能说明问题。

基准模式 Cnt得分 误差单位CalculatorBenchmark.ast avgt 10 828.924 ± 8.369 ns/opCalculatorBenchmark.manual avgt 10 115.985 ± 1.009 ns/opCalculatorBenchmark.specialized avgt 10 117.635 ± 1.500 ns/op

正如你所看到的,手动输入的方程式和专门的AST的处理速度是一样的。 ActiveJ Specializer将 ,将AST的处理速度提高了8倍。