Вступление
Active Specialized – это облегченная библиотека, которая автоматически оптимизирует ваш код для JVM и значительно ускоряет его. В отличие от традиционных методов оптимизации компилятора, он опирается на альтернативную концепцию использования информации о времени выполнения экземпляров классов, переписывая байт-код во время выполнения. Он преобразует все поля класса в поля статического класса и девиртуализирует все вызовы виртуальных методов, заменяет их вызовами статических методов.
Это действительно мощный инструмент, особенно когда речь заходит о древовидных структурах. Давайте взглянем на пример использования. |/| Мы будем использовать ActiveSpecializer для преобразования AST, которые мы получим после синтаксического анализа уравнения. В конце статьи мы проведем несколько тестов, чтобы увидеть, как Active Specialized
Синтаксический анализ уравнения.
Это руководство основано на руководстве Parsec calculator/| . Тем не менее, у него есть важное отличие. В оригинальном учебном пособии синтаксический анализ выражений для удвоения значений:
Parserparser = 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 ParserEXPRESSION = 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 ParserPARSER = 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”