Рубрики
Без рубрики

Обработка AST с активным специализированным

Intro Active Specialized – это облегченная библиотека, которая автоматически оптимизирует ваш код для… Помеченный как java, производительность.

Вступление

Active Specialized – это облегченная библиотека, которая автоматически оптимизирует ваш код для JVM и значительно ускоряет его. В отличие от традиционных методов оптимизации компилятора, он опирается на альтернативную концепцию использования информации о времени выполнения экземпляров классов, переписывая байт-код во время выполнения. Он преобразует все поля класса в поля статического класса и девиртуализирует все вызовы виртуальных методов, заменяет их вызовами статических методов.

Это действительно мощный инструмент, особенно когда речь заходит о древовидных структурах. Давайте взглянем на пример использования. |/| Мы будем использовать ActiveSpecializer для преобразования AST, которые мы получим после синтаксического анализа уравнения. В конце статьи мы проведем несколько тестов, чтобы увидеть, как Active Specialized

Синтаксический анализ уравнения.

Это руководство основано на руководстве Parsec calculator/| . Тем не менее, у него есть важное отличие. В оригинальном учебном пособии синтаксический анализ выражений для удвоения значений:

Parser parser = new OperatorTable()
    .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)
    .build(unit);

Вместо этого мы будем анализировать выражения в AST:

private static final Parser EXPRESSION = new OperatorTable()
        .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);

Например, 2 - 4 * 6 будет проанализирован следующим образом:

Мы проанализируем для AST следующее уравнение: ((2 + 2 * 2) * - x) + 5 + 1024/(100 + 58) * 50 * 37 - 100 + 2 * x ^ 2 % 3 .

Active Specialized преобразует полученный AST в набор статических конечных классов со встроенными значениями предоставленного уравнения. Во время выполнения JIT значительно оптимизирует и упорядочивает эти классы. В результате мы получим оптимизированный экземпляр выражения многократного использования.

Все, что вам нужно сделать, чтобы использовать Active Specialized , это:

public static final Parser PARSER = EXPRESSION.from(LEXER, IGNORED);

private static final Specializer SPECIALIZER = Specializer.create(Thread.currentThread().getContextClassLoader());

public static void main(String[] args) {
    double x = -1;

    CalculatorExpression expression = PARSER.parse("((2 + 2 * 2) * -x) + 5 + 1024 / (100 + 58) * 50 * 37 - 100 + 2 * x ^ 2 % 3");
    CalculatorExpression specialized = SPECIALIZER.specialize(expression);
    System.out.println(specialized.evaluate(x));
}

Контрольные показатели

Пришло время для некоторых контрольных показателей. Мы обработаем вышеупомянутое уравнение тремя различными способами и сравним производительность:

String source = "((2 + 2 * 2) * -x) + 5 + 1024 / (100 + 58) * 50 * 37 - 100 + 2 * x ^ 2 % 3";

manual = x -> ((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;
ast = SpecializerCalculatorExample.PARSER.parse(source);
specialized = SPECIALIZER.specialize(ast);
  • вручную введите уравнение
  • проанализируйте уравнение в AST и оцените его без специализации
  • проанализируйте уравнение в AST и оцените его с помощью специализации

Мы использовали JMH в режиме среднего времени в качестве эталонного инструмента. Все результаты представлены в виде наносекунд на операцию.

Benchmark                        Mode  Cnt    Score   Error  Units
CalculatorBenchmark.ast          avgt   10  828.924 ± 8.369  ns/op
CalculatorBenchmark.manual       avgt   10  115.985 ± 1.009  ns/op
CalculatorBenchmark.specialized  avgt   10  117.635 ± 1.500  ns/op

Как вы можете видеть, специализированный AST обрабатывался так же быстро, как набранное вручную уравнение, в то время как неспециализированный AST обрабатывался в 8 раз медленнее. Активный специализированный доказал свою существенную эффективность!

Оригинал: “https://dev.to/activej/processing-ast-with-activespecializer-2d5p”