David Mollitor created SPARK-59968:
--------------------------------------

             Summary: Reuse the regex Matcher across rows in LIKE and RLIKE 
codegen
                 Key: SPARK-59968
                 URL: https://issues.apache.org/jira/browse/SPARK-59968
             Project: Spark
          Issue Type: Improvement
          Components: SQL
    Affects Versions: 4.2.0
            Reporter: David Mollitor


h3. Problem

When the pattern of {{RLIKE}} or {{LIKE}} is foldable, the generated code 
compiles the {{java.util.regex.Pattern}} once and keeps it in mutable state. 
However, it still calls {{pattern.matcher(input)}} on every row:
{code:java}
value = patternRLike.matcher(input.toString()).find(0);
{code}
Each call allocates a new {{java.util.regex.Matcher}} along with its internal 
{{{}groups{}}}, {{locals}} and {{localsPos}} arrays. The JIT cannot 
scalar-replace this allocation because the Matcher escapes into the regex 
engine's recursive {{Node.match}} graph. Allocation profiles of a filter using 
a token-boundary {{RLIKE}}  show {{Matcher.<init>}} <- {{Pattern.matcher}} <- 
generated {{processNext}} at roughly 2-5% of allocated bytes.

{{LIKE}} has the same shape (using {{{}matches(){}}}) for patterns that 
{{LikeSimplification}} does not rewrite into {{StartsWith}} / {{EndsWith}} / 
{{{}Contains{}}}, such as {{{}a%b%c{}}}.
h3. Proposal

In the foldable branch of {{RLike.doGenCode}} and {{{}Like.doGenCode{}}}, build 
the {{Matcher}} once in the mutable state's init code, and reset it per row 
instead of allocating a new one:
{code:java}
// init
matcherRLike = java.util.regex.Pattern.compile("<regex>", <flags>).matcher("");
// per row
value = matcherRLike.reset(input.toString()).find(0);
{code}
 * The Matcher replaces the Pattern field (the Matcher holds its Pattern), so 
the number of mutable states does not change.
 * Codegen mutable state is per generated-object instance, so the Matcher is 
never shared across threads.
 * Results are unchanged; {{find(0)}} / {{matches()}} keep the same semantics 
as the interpreted path.

Out of scope: the interpreted path (RLike/Like are not {{{}stateful{}}}), 
non-foldable patterns, LIKE ANY / LIKE ALL, and the per-row 
{{UTF8String.toString()}} conversion.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to