Skip to content

MeshRelation: precompute exclusion lookups outside the hot loop#69

Merged
jmquigs merged 1 commit into
masterfrom
claude/optimize-meshrelation-caching-mF9rI-jmq1
May 4, 2026
Merged

MeshRelation: precompute exclusion lookups outside the hot loop#69
jmquigs merged 1 commit into
masterfrom
claude/optimize-meshrelation-caching-mF9rI-jmq1

Conversation

@jmquigs
Copy link
Copy Markdown
Owner

@jmquigs jmquigs commented May 4, 2026

isExcluded was called O(M*R) times from the nearest-neighbor loop. Each call rebuilt active-pattern closures, repeatedly uppercased the same strings, allocated "EXCLUDE." + refA / "INCLUDE." + refA, and even hit Logging.getLogOnceFn (dictionary lookup + string concat) on every iteration of every mod annotation.

Replace it with a one-time precompute that produces:

  • refUncondExcl : bool[] (any annotation == "EXCLUDE")
  • refGroups : HashSet[] (uppercased ref groups)
  • modExcludeTokens / modIncludeTokens : string[][]
    (the X parts of Exclude.X /
    Include.X, uppercased)

The returned filter is now: O(|exclude tokens| + |include tokens|) per (modIdx, refIdx) pair, with HashSet.Contains lookups, no allocations, and no logging in the hot path. Diagnostic logOnce calls are fired once at precompute time per distinct token rather than per inner-loop hit.

Behavior is preserved:

  • ref vert with "EXCLUDE" annotation -> excluded
  • mod "Exclude.X" + ref has group "X" -> excluded
  • mod "Include.X" + ref missing group "X" -> excluded
  • empty AVG arrays (either side) -> filter is a no-op, matching the previous early-out
  • out-of-range indices return false, matching the prior bounds checks

isExcluded was called O(M*R) times from the nearest-neighbor loop. Each
call rebuilt active-pattern closures, repeatedly uppercased the same
strings, allocated "EXCLUDE." + refA / "INCLUDE." + refA, and even hit
Logging.getLogOnceFn (dictionary lookup + string concat) on every
iteration of every mod annotation.

Replace it with a one-time precompute that produces:
  - refUncondExcl : bool[]              (any annotation == "EXCLUDE")
  - refGroups     : HashSet<string>[]   (uppercased ref groups)
  - modExcludeTokens / modIncludeTokens : string[][]
                                        (the X parts of Exclude.X /
                                        Include.X, uppercased)

The returned filter is now: O(|exclude tokens| + |include tokens|) per
(modIdx, refIdx) pair, with HashSet.Contains lookups, no allocations,
and no logging in the hot path. Diagnostic logOnce calls are fired once
at precompute time per distinct token rather than per inner-loop hit.

Behavior is preserved:
  - ref vert with "EXCLUDE" annotation -> excluded
  - mod "Exclude.X" + ref has group "X" -> excluded
  - mod "Include.X" + ref missing group "X" -> excluded
  - empty AVG arrays (either side) -> filter is a no-op, matching the
    previous early-out
  - out-of-range indices return false, matching the prior bounds checks
@jmquigs jmquigs merged commit ffc7e26 into master May 4, 2026
1 check passed
@jmquigs jmquigs deleted the claude/optimize-meshrelation-caching-mF9rI-jmq1 branch May 4, 2026 20:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants