Repository navigation
perf(model): read resetPropertiesStructKeyCase once per properties() call - #4632
Merged
Merged
Conversation
…call
properties() called $get("resetPropertiesStructKeyCase") once per property
inside its loop. Read it once at the top of the call instead. The flag is
kept in the variables scope rather than a new local: on RustCFML a local
assigned before `for (local.key in this)` measured slower in local runs,
while this slot is overwritten on every call and never read across calls.
Semantics are unchanged: one read per properties() call, a set() between
calls decides the next call's key casing (covered by a new regression
test), no cache or invalidation surface, and no public API change.
Part of the approved performance slice (C: properties() settings hoist).
Signed-off-by: Peter Amiri <peter@alurium.com>
The previous commit read the setting once but stored the flag in the variables scope, so two concurrent properties() calls on a shared model instance could read each other's value mid-loop (tenant config resolves through $get()), and a callback that re-enters properties() could overwrite the outer loop's flag. Keep the single read, but hold it in a local as the brief prescribes: one read per call, a set() between calls still decides the next call's casing, no instance state. Part of the approved performance slice (C: properties() settings hoist). Signed-off-by: Peter Amiri <peter@alurium.com>
4 tasks done
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Part C of the approved performance slice.
properties()read$get("resetPropertiesStructKeyCase")once per property inside its loop; it now reads the setting once at the top of the call.local.rv = {}; local.propNames = propertyNames(); + local.resetPropertyKeyCase = $get("resetPropertiesStructKeyCase"); for (local.key in this) { ... - if ($get("resetPropertiesStructKeyCase")) { + if (local.resetPropertyKeyCase) {The flag is a call-local (
local.resetPropertyKeyCase), exactly as the brief §C.2 prescribes — not an instance slot. That matters for correctness: model instances can be shared or long-lived,$get()honours per-tenant overrides, and avariables-scope flag would let two concurrentproperties()calls on the same instance read each other's value mid-loop, and let a callback that re-entersproperties()overwrite the outer loop's flag. A local has neither problem.Semantics (unchanged)
properties()call; aset()between two calls decides the casing of the next call's keys.$getmemo (brief §C.3) is not used.Regression test
Added to
propertiesSpec.cfc: "reads resetPropertiesStructKeyCase once per call, so a set between calls is visible". It togglesset(resetPropertiesStructKeyCase = false)thentruebetween twoproperties()calls and asserts the returned key spelling follows — the raw this-scope spelling when off, the canonicalpropertyNames()spelling when on. Both spellings are read from the engine at runtime so the test is valid on Adobe (upper-case this scope) and Lucee (lower-case), and it guards against any future per-request memo.Measured impact
The microbench is small and inconclusive on this host; I am reporting it as such rather than claiming a win:
$get("environment")costs ~1.6 µs/call on RustCFML (in-model and external), so removing 11–12 calls perproperties()call is ~18 µs of work.variablesscope; it was replaced with the brief's call-local for the thread/tenant and recursion reasons above. Correctness beats a sub-µs read, and the PR's own CI is the authoritative check.Verification run on this change (head
7a25a6bc6)bash tools/test-local.sh model→ 1502 passed (includes the regression test, green)bash tools/test-local.sh database→ 189 passedtools/test-matrix.sh lucee7 sqlitepassed during development (full suite); PR CI re-runs the engine matrix on this head.Part C of the approved performance slice; PR A (#4631) is merged, PR B was dropped after its premise measured as a regression.