Repository navigation
Conversation
…opying them The workspace copied the parse tree of every statement into the analyser (AnalysableStatement owned its tree), and the analyser copied them all once more for the file context. Analysing a file of 5,000 statements peaked at twice its cached trees. AnalysableStatement::root is now an Arc of the tree that the workspace caches, and the file context borrows them. The other statement mappers share the trees too; the formatter copies a tree only when it replaces a function body in it.
This was referenced Oct 25, 2026
Closed
Collaborator
Author
|
Superseded by #1002 (rebuild of the document caches and walk). |
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.
Stacked on #964.
#951 measured a transient peak of 265 MiB for analysing a single 5,000-statement file, about twice what its cached parse trees take. The workspace cached each statement's tree behind an
Arc, but every analysis made two copies of it:AnalyserDiagnosticsMapperdeep-cloned each tree intoAnalysableStatement::root. That mapper is also whatwalk_statementsuses, so hover and inlay hints copied every statement before the cursor too.Analyser::analysecloned all roots again into aVec<NodeEnum>forAnalysedFileContext.The CLI runs one file per rayon worker, so the peak is multiplied by the number of workers.
What changed
AnalysableStatement::rootis anArc<NodeEnum>, andAnalysableStatement::new(root: impl Into<Arc<NodeEnum>>, range)still takes an owned tree. That is the only public API change: callers that build statements from owned trees (the rules tests, the regress test) compile unchanged.AnalysedFileContext::stmtsandprevious_stmts()are&[&NodeEnum]. The rules that look at other statements match through the reference unchanged.Result<Arc<NodeEnum>, SyntaxDiagnostic>(pg_query::ParseResult), and all statement mappers hand out the sharedArc. That includesTypecheckDiagnosticsMapper, which also deep-cloned the wholeCREATE FUNCTIONfor each statement in its body.Arc::make_mut, which copies only that function's tree.Measurements
tests/memory_bounds.rs, release build, 20 documents × 5,000 statements. The test now also prints how long the CLI pass takes (open, diagnostics, close for each file).What is retained doesn't change, since it is the cache itself. The peaks now stay close to it, and dropping the copies also makes the analysis about a third faster.
Tests
The existing suites cover it:
pgls_analyser: rules specs and the Postgres regression test;pgls_workspace, including formatting of SQL function bodies throughmake_mut, and the memory and edit-churn tests;pgls_lsp.Not covered
pgls_typecheck's EXPLAIN path and the formatter take&NodeEnumand don't copy. I didn't look for copies outside the workspace and the analyser.