perf(references): компактный SymbolOccurrence через short-координаты#4276
Conversation
Профилирование analyze на большой конфигурации (cpm, ~13k файлов) показало, что SymbolOccurrence — крупнейший объект приложения в reference-индексе: ~6 млн экземпляров, ~239 МБ живого heap (40 байт/шт при сжатых указателях). Координаты диапазона (строка/столбец начала и конца) в подавляющем большинстве файлов укладываются в short. Зеркалим уже принятую в проекте оптимизацию VariableSymbol (Int/Short-реализации): SymbolOccurrence становится sealed-интерфейсом с фабрикой of(...), которая выбирает ShortBasedSymbolOccurrence (4×short) для обычных координат и IntBasedSymbolOccurrence (4×int) для файлов со строками/столбцами > Short.MAX_VALUE. Аксессоры координат по-прежнему возвращают int, публичный API не меняется. JOL: 40 → 32 байта на экземпляр (-20%); на 6 млн вхождений ≈ -48 МБ живого heap. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_01HLvkKQCwBjTHwuZ4EGBQK6
Микробенчмарк создания SymbolOccurrence через фабрику of(): параметр shortBased переключает координаты между укладывающимися в short и выходящими за его пределы. С -prof gc подтверждает 40 → 32 байта на экземпляр (gc.alloc.rate.norm). Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]> Claude-Session: https://claude.ai/code/session_01HLvkKQCwBjTHwuZ4EGBQK6
📝 WalkthroughWalkthrough
ChangesSymbol occurrence storage
Estimated code review effort: 3 (Moderate) | ~20 minutes Sequence Diagram(s)sequenceDiagram
participant Caller
participant SymbolOccurrence
participant ShortBasedSymbolOccurrence
participant IntBasedSymbolOccurrence
Caller->>SymbolOccurrence: of(occurrenceType, symbol, uri, coordinates)
SymbolOccurrence->>SymbolOccurrence: evaluate fitsShort(coordinates)
alt coordinates fit short
SymbolOccurrence->>ShortBasedSymbolOccurrence: construct occurrence
ShortBasedSymbolOccurrence-->>Caller: SymbolOccurrence
else coordinates exceed short
SymbolOccurrence->>IntBasedSymbolOccurrence: construct occurrence
IntBasedSymbolOccurrence-->>Caller: SymbolOccurrence
end
Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
src/main/java/com/github/_1c_syntax/bsl/languageserver/references/model/ShortBasedSymbolOccurrence.java (1)
46-54: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winMake record implementations package-private to enforce encapsulation.
Both records are strictly meant to be instantiated via the
SymbolOccurrence.of()factory, which fully abstracts the storage selection. Keeping the recordspublicallows direct instantiation from outside the package, which bypasses the factory and could lead to logically identical occurrences having different runtime classes (resulting in inconsistentequals()andhashCode()behavior despitecompareTo() == 0).Since the
SymbolOccurrencesealed interface is public, its permitted implementations can securely safely remain package-private to hide the internal storage optimizations.
src/main/java/com/github/_1c_syntax/bsl/languageserver/references/model/ShortBasedSymbolOccurrence.java#L46-L54: remove thepublicmodifier to make the record package-private.src/main/java/com/github/_1c_syntax/bsl/languageserver/references/model/IntBasedSymbolOccurrence.java#L40-L48: remove thepublicmodifier to make the record package-private.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/main/java/com/github/_1c_syntax/bsl/languageserver/references/model/ShortBasedSymbolOccurrence.java` around lines 46 - 54, Make both record implementations package-private by removing the public modifier from ShortBasedSymbolOccurrence in src/main/java/com/github/_1c_syntax/bsl/languageserver/references/model/ShortBasedSymbolOccurrence.java:46-54 and IntBasedSymbolOccurrence in src/main/java/com/github/_1c_syntax/bsl/languageserver/references/model/IntBasedSymbolOccurrence.java:40-48, ensuring callers use the public SymbolOccurrence.of() factory.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In
`@src/main/java/com/github/_1c_syntax/bsl/languageserver/references/model/ShortBasedSymbolOccurrence.java`:
- Around line 46-54: Make both record implementations package-private by
removing the public modifier from ShortBasedSymbolOccurrence in
src/main/java/com/github/_1c_syntax/bsl/languageserver/references/model/ShortBasedSymbolOccurrence.java:46-54
and IntBasedSymbolOccurrence in
src/main/java/com/github/_1c_syntax/bsl/languageserver/references/model/IntBasedSymbolOccurrence.java:40-48,
ensuring callers use the public SymbolOccurrence.of() factory.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: b5d6d6a4-88ff-463f-852d-5c2f5b7b642a
📒 Files selected for processing (5)
src/jmh/java/com/github/_1c_syntax/bsl/languageserver/references/SymbolOccurrenceCreate.javasrc/main/java/com/github/_1c_syntax/bsl/languageserver/references/model/IntBasedSymbolOccurrence.javasrc/main/java/com/github/_1c_syntax/bsl/languageserver/references/model/ShortBasedSymbolOccurrence.javasrc/main/java/com/github/_1c_syntax/bsl/languageserver/references/model/SymbolOccurrence.javasrc/test/java/com/github/_1c_syntax/bsl/languageserver/references/model/SymbolOccurrenceTest.java
|



Описание
Профилирование
analyzeна большой конфигурации (cpm, ~13k файлов) показало, чтоSymbolOccurrence— крупнейший объект приложения в reference-индексе: ~6 млн экземпляров,~239 МБ живого heap (40 байт/шт при сжатых указателях), под доминатором
WorkspaceBeanScope→
ReferenceIndex.Координаты диапазона в подавляющем большинстве файлов укладываются в
short. Зеркалю ужепринятую в проекте оптимизацию
VariableSymbol(Int/Short-реализации):SymbolOccurrence→sealed interfaceс фабрикойof(...);ShortBasedSymbolOccurrence(4×short) для обычных координат,IntBasedSymbolOccurrence(4×
int) для файлов со строками/столбцами> Short.MAX_VALUE;int— публичный API не меняется.Замеры
JMH (
SymbolOccurrenceCreate,-prof gc): 40 → 32 байта/экземпляр (−20 %).cpm
analyze(develop vs ветка),jmap -histo:live:SymbolOccurrence(класс)Чистый выигрыш по памяти без стоимости по CPU/wall.
Связанные задачи
Closes
Чеклист
Общие
SymbolOccurrenceTest+ существующие тесты reference-индекса)gradlew precommit) — прогонялtest+spotlessCheckДополнительно
SymbolOccurrenceTest: выбор реализации (short / границаShort.MAX_VALUE/ int-фолбэк),equals/hashCode/compareTo(в т.ч. кросс-реализационно), реконструкцияrange()/startPosition().IntBased.🤖 Generated with Claude Code
Summary by CodeRabbit
Improvements
Tests
Refactor