Skip to content

perf(model): the WHERE literal scanner is quadratic on RustCFML (Mid() costs O(index)); BoxLang finder calls are super-linear at large values #3903

Closed

Description

@bpamiri

Repro: on RustCFML (v0.693.0), bind a long value in a finder, e.g. model("author").findAllByLastName(value = RepeatString("z", 30000)), and time it at 3k and 30k characters.

Actual: time grows about 70x for a 10x longer value (3k: 9ms, 30k: ~620ms; 100k took 22.8s in CI). $maskWhereLiterals in vendor/wheels/model/sql.cfm walks the string with Mid(where, i, 1), and on RustCFML Mid() walks the string to reach index i, so the scan is O(n^2). A bare Mid loop shows the same growth (10k: 63ms, 100k: 6420ms). Lucee 7 and Adobe 2023 are linear (about 10x for a 10x step). BoxLang, corrected 2026-10-01: the binder alone is linear on BoxLang (matrix 36824391525 timed $addWhereClause + $addWhereClauseParameters: 8.5-9.9x for a 10x step on every database). The super-linearity seen earlier (#3875 run 36821821649: a full finder call, plain 50k 193ms -> 500k 8103ms = 42-51x, quotes 29-32x) is in the query/driver path for very long bound values, not the scanner. Profile a 500k-character bound finder on BoxLang to locate it.

Expected: linear on every engine.

Fix location: vendor/wheels/model/sql.cfm $maskWhereLiterals: avoid per-character Mid(), e.g. iterate a Java char array (where.toCharArray()) or jump between quote positions with Find(). Also report Mid() cost upstream to RustCFML. Once linear, tighten the RustCFML plan in finderValueBindingSpec.linearityPlan() ("no worse than quadratic") to the Lucee/Adobe bound. BoxLang can move back to the 25x bound now, since its binder measures ~9-10x.


Found during 4.1.2 release testing. Repros are on develop @ 26245b53d unless the issue says otherwise.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugperformancePerformance work (profiling, hot-path optimization)

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions