yongster opened a new pull request, #11137: URL: https://github.com/apache/arrow-rs/pull/11137
# Which issue does this PR close? - Closes #11084. # Rationale for this change Array/array `LIKE` / `ILIKE` / `NLIKE` / `NILIKE` go through `binary_predicate`, which only reused the immediately previous pattern. Two or more complex (Regex-backed) patterns that alternate — or any low-cardinality pattern column that is not grouped — therefore re-ran `regex_like` + `RegexBuilder::build` on almost every row. Performance then depended on row order even when the logical workload had only a few distinct patterns. Simple patterns (`x%`, `%x`, `%x%`, equality) do not compile a Regex and were already cheap. The scalar path already builds one `Predicate` and is unchanged. # What changes are included in this PR? - Keep the existing previous-pattern fast path so consecutive duplicates do not pay an extra lookup. - Add a bounded cache (8 entries) of compiled **Regex** predicates, keyed by borrowed `&str` from the pattern array. - Once the cache is full, additional patterns are evaluated without being retained, so a unique pattern per row cannot accumulate an unbounded number of `Regex` values. - Keep `previous` even for a pattern that was not inserted into the cache, so a consecutive run of an uncached pattern does not recompile every row. - Prefix/suffix/contains/equality predicates are not cached; rebuilding them is cheaper than cache bookkeeping. - Tests for alternating complex patterns across LIKE/NLIKE/ILIKE/NILIKE (Utf8 / LargeUtf8 / Utf8View / Dictionary), mixed nulls, and more distinct patterns than the cache cap. - Criterion benches for consecutive complex, alternating complex, simple alternating, and all-unique complex array/array LIKE. # Are these changes tested? Yes. `cargo test -p arrow-string --lib like`: 63 passed. Independent remeasurement of the public `like` / `ilike` APIs on arm64 macOS, 1,024 rows of `"xxxxxxxx"`: | Case | Before | After | |---|---:|---:| | LIKE, one complex pattern, consecutive | 52.4 µs | 40.0 µs | | LIKE, two complex patterns, alternating | 21.18 ms | 62.1 µs (~341×) | | ILIKE, two complex patterns, alternating | 21.64 ms | 65.6 µs (~330×) | | LIKE, two simple patterns (`x%` / `%x`), alternating | 13.2 µs | 15.9 µs | | LIKE, 1,024 unique complex patterns | 18.86 ms | 18.54 ms | Criterion (`cargo bench -p arrow --features test_utils --bench comparison_kernels -- "like_utf8 array"`) after the change: | Bench | time | |---|---:| | `like_utf8 array complex consecutive` | 38.4 µs | | `like_utf8 array complex alternating` | 58.8 µs | | `ilike_utf8 array complex alternating` | 59.6 µs | | `like_utf8 array simple alternating` | 15.9 µs | | `like_utf8 array complex unique` | 18.6 ms | `cargo fmt --all -- --check` and `cargo clippy -p arrow-string --lib --all-targets -- -D warnings` pass. # Are there any user-facing changes? No. Logical results are unchanged; this is an internal reuse policy for compiled Regex predicates. AI assistance: implementation and tests were drafted with AI and then reviewed, corrected (Regex-only cache so simple patterns do not regress), and remeasured locally. -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
