Skip to content

perf(semantic): compute a feature's redefinition closure once per model - #1353

Merged
HuiJun merged 2 commits into
developfrom
perf/implicit-parameter-position-from-memo
Oct 21, 2026
Merged

HuiJun merged 2 commits into
developfrom
perf/implicit-parameter-position-from-memo

Conversation

@devin-ai-integration

@devin-ai-integration devin-ai-integration Bot commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

What and why

In the 0.11.0 release-gate measurement internal/exec/runtime BenchmarkNewRootFrame reads 36 → 55 allocs/op against 0.10.1 (12.5 → 13.8 KiB/op). The allocation profile puts the whole difference under Context.holdFeature, which since #1057 asks semantics.Model.AllRedefinedFeatures for every feature a root frame holds (0.10.1 asked the memoized RedefinedFeatures, explicit clauses only). AllRedefinedFeatures rebuilt its visited set and visit closure on every call, and the implicit parameter redefinitions it walks (implicitParameterTargets) rebuilt the owner's owned-parameter list (positionalParameters(ownedParameters(owner))) on every query to find the parameter's position — a list parametersOf(owner) already memoizes, and whose owned entries come first in the same order.

Changes, all in internal/semantic/semantics:

  • AllRedefinedFeatures is a journaled per-symbol table (allRedefined, keyed like nestedRedefs and invalidated with the declaration), so the closure of a feature is computed once per model. The walk runs under a resolver lookup frame and is cached only when that frame settled: a closure cut short by a redefinition still resolving its clause, or by an owner whose parameter list is still being computed, is answered but recomputed on the next query — the same rule RedefinedFeatures follows.
  • parametersOf records its lookup depth and cuts a re-entrant reader short (computingParams, like computingRedefined) instead of answering it silently with the empty seed, and does not memoize its own list when its frame did not settle.
  • implicitParameterTargets reads the parameter's position from m.parametersOf(owner).positional instead of rebuilding the owned list.

Same redefinitions, same positions; only the repeated work goes.

How it was verified

Checklist

  • make test and make lint pass locally (the packages above locally; the full suite runs in CI)
  • Tests added or updated for the change
  • Documentation extended where it already covers the surface (no doc covers this internal)
  • Changelog entry added as changes/unreleased/<slug>.<section>.md, not as an edit to CHANGELOG.md
  • baselines regenerated and make docs-counts run if a gate count moved (no gate count moved)
  • No internal work-item labels (waves, slices, F4, K5) in the body, docs, or changelog

Link to Devin session: https://nasa-jpl-demo.devinenterprise.com/sessions/cf22d7a746814d20b2f0eaf11682fef9
Open in Devin Desktop: https://nasa-jpl-demo.devinenterprise.com/desktop/session/cf22d7a746814d20b2f0eaf11682fef9?variant=devin
Requested by: @HuiJun

AllRedefinedFeatures rebuilt its visited set and closure on every call, and the
implicit parameter redefinitions behind it rebuilt the owner's owned-parameter
list on every query although parametersOf memoizes that list. An execution
root frame asks for the closure of every feature it holds, so each frame paid
for both. The closure is now a journaled per-symbol table like the other
semantic memos, and the position lookup reads the memoized list.

Co-Authored-By: jason.han <hanhuijun@gmail.com>
@devin-ai-integration

Copy link
Copy Markdown
Contributor Author

I'll fix CI failures and address comments from users with write access. I'll skip comments containing "(aside)".

  • Disable automatic comment, CI, and merge conflict monitoring

devin-ai-integration[bot]

This comment was marked as resolved.

A closure walked while a guard cut a nested query short — a redefinition
still resolving its clause, or an owner whose parameter list is still being
computed — may lack a target. AllRedefinedFeatures now runs under a resolver
lookup frame and caches only when that frame settled, and parametersOf cuts a
re-entrant reader short the way RedefinedFeatures does, instead of answering
it silently with an empty list.

Co-Authored-By: jason.han <hanhuijun@gmail.com>
@devin-ai-integration
devin-ai-integration Bot marked this pull request as ready for review October 21, 2026 11:57
@HuiJun
HuiJun merged commit a662c2b into develop Oct 21, 2026
50 checks passed
@HuiJun
HuiJun deleted the perf/implicit-parameter-position-from-memo branch October 21, 2026 14:01
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.

1 participant