From e8243dc762849cf9545f45182865ca2b1ec7089e Mon Sep 17 00:00:00 2001 From: Knut Wannheden Date: Thu, 29 Oct 2026 09:26:10 +0100 Subject: [PATCH] perf: cut the lookahead scans in ComplexExpressionList `ComplexExpressionList()` parses every function argument list, and its lookaheads took 11% of parse CPU on `performance.sql`. The loop's `LOOKAHEAD(2) ","` scanned through the choice behind the comma, so every nested lookahead ran once in the scan and again when the choice was entered. And JavaCC scanned a token of `Expression()` before entering the default alternative of both choices, which a semantic lookahead on that alternative avoids. The loop now checks for a comma by token kind and the default alternatives enter `Expression()` directly. `SimpleExpressionList()` gets the same two changes. Parser CPU per parse drops from 33.5 ms to 29.8 ms (-11.5%, three interleaved pairs), and `./gradlew jmh` from 39.31 to 32.06 ms/op. --- .../jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt index 7339e68ba..a2122b90a 100644 --- a/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt +++ b/src/main/jjtree/net/sf/jsqlparser/parser/JSqlParserCC.jjt @@ -12783,11 +12783,11 @@ ExpressionList SimpleExpressionList(): { expr=SimpleExpression() { expressions.add(expr); } ( - LOOKAHEAD(2, {!interrupted} ) "," + LOOKAHEAD({ !interrupted && getToken(1).kind == K_COMMA }) "," ( LOOKAHEAD( RelObjectName() "->", { !isJsonArrowDialect() } ) expr=LambdaExpression() | - expr=SimpleExpression() + LOOKAHEAD({ !interrupted }) expr=SimpleExpression() ) { expressions.add(expr); @@ -12835,14 +12835,15 @@ ExpressionList ComplexExpressionList(): | LOOKAHEAD(2, { isNamedParameterAssignmentAhead() }) expr=PostgresNamedFunctionParameter() | - expr=Expression() + // JavaCC scans an unguarded alternative's first token; a semantic-only lookahead enters directly + LOOKAHEAD({ !interrupted }) expr=Expression() ) { expressions.add(expr); } ( - LOOKAHEAD(2, {!interrupted}) "," + LOOKAHEAD({ !interrupted && getToken(1).kind == K_COMMA }) "," ( LOOKAHEAD(2, { isNamedParameterAssignmentAhead() }) expr=OracleNamedFunctionParameter() | @@ -12850,7 +12851,7 @@ ExpressionList ComplexExpressionList(): | LOOKAHEAD( RelObjectName() "->", { !isJsonArrowDialect() } ) expr=LambdaExpression() | - expr=Expression() + LOOKAHEAD({ !interrupted }) expr=Expression() ) { expressions.add(expr); } )*