Skip to content

perf(repl): collect referenced roots only when a reference is unresolved - #1624

Merged
HuiJun merged 1 commit into
developfrom
perf/resolve-first-lazy-roots
Oct 28, 2026
Merged

HuiJun merged 1 commit into
developfrom
perf/resolve-first-lazy-roots

Conversation

@devin-ai-integration

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

Copy link
Copy Markdown
Contributor

What and why

Since the resolve-first dependency search landed (#1528, fix/resolve-first-dependency-search), Session.resolveReferences walked every submission's text twice before checking whether anything was unresolved: project.ImportedRoots and project.ReferencedRoots are both reflection walks (ast.Inspect) over the whole tree, and undeclaredRoots then filtered every root out when the submission had no unresolved reference. On a 1 000-element model load that was 14 130 allocations and about 14 % of the wall time per load.

The method now gathers the unresolved subjects first and returns when there are none, collects the imported roots only then, and the referenced roots only when the imports answered nothing (the branch that already needed them). Behaviour with an unresolved import or qualified name is unchanged; the existing on-demand loading tests in workspace_test.go cover it.

Measured (BenchmarkLoadModel/elements=1000, internal/frontend/repl, go1.27.3, same machine, single 10× run; the six-round benchstat table follows in a comment):

revision sec/op B/op allocs/op
v0.11.0 source (ddf4df000) 108.7 ms 58.26 MB 533 100
develop (ddfbb9446) 144.5 ms 62.63 MB 546 708
develop + this PR 123.9 ms 60.95 MB 532 578

The remaining sec/op gap to v0.11.0 is the reflection walker's per-field type lookups (fixed separately by perf/ast-inspect-field-plan); the B/op residual (+4.6 %) is the TypedBy spans and stdlib snapshot growth of #1478, which this PR does not touch.

How it was verified

  • TestResolvingNothingDoesNotWalkTheText (new): testing.AllocsPerRun of resolveReferences over 50 vs 100 fully resolved packages must not grow; fails on develop (the walk scales with the text), passes here.
  • go build ./..., go vet ./..., gofmt -l . empty, python3 scripts/changelog.py check.
  • go test -count=1 ./internal/frontend/repl ./internal/frontend/lsp ./tests/perf, go test -count=1 -race ./internal/frontend/repl (results pasted in a comment when complete).

Overlap with open PRs

Touches internal/frontend/repl/workspace.go only; none of the open fix/sonar-* PRs (#1606 internal/exec/runtime, #1610 internal packages) edits that file. Re-checked at push time: no perf/* branch or PR on the remote.

Checklist

  • make test and make lint pass locally (touched packages; see above)
  • Tests added or updated for the change
  • Documentation extended where it already covers the surface (none covers this)
  • Changelog entry added as changes/unreleased/resolve-first-lazy-roots.changed.md
  • baselines regenerated (no gate count moved)
  • No internal work-item labels in the body, docs, or changelog

resolveReferences walked every submission's text twice (ImportedRoots and
ReferencedRoots, both reflection walks over the whole tree) before checking
whether anything was unresolved; undeclaredRoots then filtered every root
out when nothing was. Gather the unresolved subjects first, return when there
are none, and collect the referenced roots only when the imports answered
nothing. A differential test asserts the cost no longer grows with the text.

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

Copy link
Copy Markdown
Contributor Author

Local gates on head 3ef59e1 (go1.27.3):

go build ./...      ok
go vet ./...        ok
gofmt -l .          (empty)
python3 scripts/changelog.py check   ok
ok  github.com/Open-MBEE/OpenSysML/internal/frontend/repl   28.850s
ok  github.com/Open-MBEE/OpenSysML/internal/frontend/lsp    12.837s
ok  github.com/Open-MBEE/OpenSysML/tests/perf                0.177s
go test -count=1 -race ./internal/frontend/repl   ok  114.617s

The failing "From the tree" check (validate-action.yml, triggered because this PR touches internal/frontend/repl/**) is sysml -validate examples exiting 2 on one pre-existing error in examples/self-model/asciidoc/markup.sysml (document-plan-markup-tool-missing: the workflow builds sysml but installs no AsciiDoc converter). The develop binary at ddfbb94 reports the identical error on the same tree; this PR's diff of the validate output against develop is empty.

@devin-ai-integration
devin-ai-integration Bot marked this pull request as ready for review October 28, 2026 11:03

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no bugs or issues to report.

Devin Review

@devin-ai-integration

Copy link
Copy Markdown
Contributor Author

The one red check on this head, From the tree (validate-action.yml), fails with sysml -validate exited 2 and is pre-existing: the same sysml -validate examples run on origin/develop (ddfbb94) with the same build reports the same one error, document-plan-markup-tool-missing (the AsciiDoc converter the action's tree does not install), plus eight warnings. This PR changes only internal/frontend/repl's dependency search and does not touch validation or the examples. Every other check on the head is green.

@HuiJun
HuiJun merged commit 1f97116 into develop Oct 28, 2026
55 of 56 checks passed
@HuiJun
HuiJun deleted the perf/resolve-first-lazy-roots branch October 28, 2026 13:10
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