Skip to content

perf(context): объединить обход регионов и переменных в один проход#4176

Merged
nixel2007 merged 2 commits into
developfrom
claude/perf-symbol-tree-single-pass
Jun 22, 2026
Merged

perf(context): объединить обход регионов и переменных в один проход#4176
nixel2007 merged 2 commits into
developfrom
claude/perf-symbol-tree-single-pass

Conversation

@nixel2007

@nixel2007 nixel2007 commented Jun 20, 2026

Copy link
Copy Markdown
Member

Зачем

Symbol tree открытого документа перестраивается на каждый keystroke. При сборке дерева RegionSymbolComputer и VariableSymbolComputer выполняли два отдельных полных обхода AST вглубь (оба спускаются в тела методов). По профилю набора текста на большом модуле (SSL 3.2, УправлениеДоступомСлужебный, 48 399 строк) обход визиторами (AbstractParseTreeVisitor.visitChildren) — заметная доля стоимости ребилда (~20% self-time по JFR), и половина её приходилась на второй, дублирующий обход.

Что меняется

Наборы перекрываемых узлов у этих двух визиторов не пересекаются:

  • регионы — директивы #Область/#КонецОбласти (visitRegionStart/visitRegionEnd);
  • переменные — объявления переменных/параметров, lvalue, циклы (visitModuleVarDeclaration/visitSub/visitSubVarDeclaration/visitParam/visitLValue/visitForStatement/visitForEachStatement).

Поэтому сбор регионов добавлен поверх обхода переменных в новом RegionVariableSymbolComputer (наследник VariableSymbolComputer) — оба набора override'ов работают в одном visitFile, и два полных обхода схлопываются в один.

  • VariableSymbolComputer оставлен самостоятельным (используется отдельно) и не изменён.
  • MethodSymbolComputer не трогается: его обход поверхностный (не спускается в тела методов), и от его результата зависит резолвинг scope переменных — поэтому методы по-прежнему считаются первым, отдельным проходом.
  • RegionSymbolComputer удалён (использовался только в SymbolTreeComputer).

Замеры

JFR, тот же модуль УправлениеДоступомСлужебный (48 399 строк), эмуляция набора текста, 204 нажатия, A/B на одинаковой сборке:

rebuild min p50 mean visitChildren (self, JFR)
до (2 обхода) 1115 мс 1237 мс 1251 мс 19.4%
после (1 обход) 1030 мс 1120 мс 1153 мс 15.3%

8% быстрее (~100 мс с ~1.2 с), стабильно по min/p50/mean. Выигрыш растёт с размером модуля (полный обход — O(размер файла)).

Проверка

  • compileJava зелёный.
  • Тесты дерева символов зелёные: SymbolTreeComputerTest, DocumentContextTest (в т.ч. testGetRegionsFlatComputesAllLevels — вложенность регионов), VariableSymbolComputerTest, MethodSymbolComputerTest, MethodSymbolComputerConstructorTest.

Базируется на develop, независимо от #4174 и #4175.

🤖 Generated with Claude Code


Generated by Claude Code

Summary by CodeRabbit

  • Refactor
    • Improved language server symbol computation by unifying the processing of variable and region symbols into a single pass.
    • Region symbols are now retained for subsequent steps in symbol tree building, improving consistency and performance during indexing.

При перестроении дерева символов на каждый keystroke RegionSymbolComputer и
VariableSymbolComputer выполняли два отдельных полных обхода AST вглубь. По
профилю набора текста на большом модуле (УправлениеДоступомСлужебный, 48k строк)
обход визиторами (AbstractParseTreeVisitor.visitChildren) — заметная доля
стоимости ребилда.

Наборы перекрытых узлов у этих визиторов не пересекаются (директивы
#Область/#КонецОбласти против объявлений переменных/параметров/lvalue/циклов),
поэтому сбор регионов добавлен поверх обхода переменных в новом
RegionVariableSymbolComputer (наследник VariableSymbolComputer) — два полных
обхода схлопнуты в один. VariableSymbolComputer остаётся самостоятельным.

Замер (JFR, тот же модуль, 204 нажатия): rebuild p50 1237→1120 мс, min
1115→1030 мс (~8%); доля visitChildren 19.4%→15.3%.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HcK3qVwTH91rXtgprGmoWr
@coderabbitai

coderabbitai Bot commented Jun 20, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 17fa9671-5a78-4fa4-8891-d1234cef17ac

📥 Commits

Reviewing files that changed from the base of the PR and between 866c458 and 3d235aa.

📒 Files selected for processing (1)
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/context/computer/RegionVariableSymbolComputer.java
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/main/java/com/github/_1c_syntax/bsl/languageserver/context/computer/RegionVariableSymbolComputer.java

📝 Walkthrough

Walkthrough

RegionSymbolComputer is replaced by RegionVariableSymbolComputer, which extends VariableSymbolComputer to perform a single AST traversal that collects both variable symbols and region symbols. SymbolTreeComputer is updated to instantiate this combined computer and retrieve both outputs from it.

Changes

Combined region and variable symbol computation

Layer / File(s) Summary
RegionVariableSymbolComputer class and region finalization
src/main/java/com/github/_1c_syntax/bsl/languageserver/context/computer/RegionVariableSymbolComputer.java
Renames RegionSymbolComputer to RegionVariableSymbolComputer extending VariableSymbolComputer. Constructor gains ModuleSymbol and methods parameters. compute() clears state, delegates to super.compute(), and returns List<VariableSymbol>. New getRegions() exposes the accumulated region set. visitRegionEnd removes the intermediate local variable and directly calls builder.build() into the regions set.
SymbolTreeComputer call site
src/main/java/com/github/_1c_syntax/bsl/languageserver/context/computer/SymbolTreeComputer.java
Replaces two separate RegionSymbolComputer and VariableSymbolComputer instantiations with a single RegionVariableSymbolComputer, calling compute() for variables and getRegions() for regions.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐇 Two hops through the AST — now one!
The region and the variable run
Together in a single pass,
No double-traversal to harass.
One computer, twice the fun! 🌿

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 16.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main optimization: combining region and variable AST traversals into a single pass, which is the core change across both modified files.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/perf-symbol-tree-single-pass

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

…omputer

Класс RegionSymbolComputer удалён в этом PR, а его {@link} остался в javadoc
RegionVariableSymbolComputer → Xdoclint:all валил задачу javadoc (reference
not found). Заменено на прозаическое описание.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HcK3qVwTH91rXtgprGmoWr
@sonarqubecloud

Copy link
Copy Markdown

@github-actions

Copy link
Copy Markdown
Contributor

Test Results

 3 516 files  ±0   3 516 suites  ±0   1h 34m 28s ⏱️ + 1m 17s
 3 455 tests ±0   3 437 ✅ ±0   18 💤 ±0  0 ❌ ±0 
20 730 runs  ±0  20 618 ✅ ±0  112 💤 ±0  0 ❌ ±0 

Results for commit 3d235aa. ± Comparison against base commit 346bcef.

@nixel2007
nixel2007 merged commit 4dbf671 into develop Jun 22, 2026
37 checks passed
@nixel2007
nixel2007 deleted the claude/perf-symbol-tree-single-pass branch June 22, 2026 06:03
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