Skip to content

Commit dcdcbbe

Browse files
committed
perf: fix top-5 hot-path allocation anti-patterns
1. lsp/completion: add zero-alloc hasPrefixFold helper and use it in anchorItems, refLabelItems, kindItems, directivePathItems — removes one strings.ToLower allocation per symbol/kind/file on every LSP completion request. 2. lsp/completion: return nil (not []completionItem{}) from helper early-exits; outer handleCompletion already converts nil → []. 3. lsp/symbols: return nil (not []documentSymbol{}) from buildOutline when index has no file entry. 4. rules/requiredstructure: compile buildFieldPattern once per body line instead of once per field on that line, eliminating redundant regexp.MustCompile calls when a line contains multiple {field} references. 5. rules/concisenessscoring/classifier: return nil (not []string{}) from dedupeSorted on empty input, per project convention. https://claude.ai/code/session_01EekcsPRZ89tht6Fsh3y4d8
1 parent b2b2d68 commit dcdcbbe

4 files changed

Lines changed: 28 additions & 16 deletions

File tree

internal/lsp/completion.go

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ func (s *Server) completionItems(ctx index.CompletionContext, rel string, idx *i
5252
return s.anchorItems(rel, ctx.Prefix, idx, true)
5353
case index.CompletionAnchorOtherFile:
5454
if ctx.TargetFile == "" {
55-
return []completionItem{}
55+
return nil
5656
}
5757
return s.anchorItems(ctx.TargetFile, ctx.Prefix, idx, false)
5858
case index.CompletionRefLabel:
@@ -62,7 +62,16 @@ func (s *Server) completionItems(ctx index.CompletionContext, rel string, idx *i
6262
case index.CompletionDirectivePath:
6363
return s.directivePathItems(rel, ctx.Prefix, idx)
6464
}
65-
return []completionItem{}
65+
return nil
66+
}
67+
68+
// hasPrefixFold reports whether s begins with prefixLower (already lowercased),
69+
// case-insensitively and without allocating.
70+
func hasPrefixFold(s, prefixLower string) bool {
71+
if len(s) < len(prefixLower) {
72+
return false
73+
}
74+
return strings.EqualFold(s[:len(prefixLower)], prefixLower)
6675
}
6776

6877
// anchorItems returns completion items for heading anchors in the given file.
@@ -71,15 +80,15 @@ func (s *Server) completionItems(ctx index.CompletionContext, rel string, idx *i
7180
func (s *Server) anchorItems(file, prefix string, idx *index.Index, sameFile bool) []completionItem {
7281
fe, ok := idx.File(file)
7382
if !ok {
74-
return []completionItem{}
83+
return nil
7584
}
7685
prefixLower := strings.ToLower(prefix)
7786
var items []completionItem
7887
for _, sym := range fe.Symbols {
7988
if sym.Kind != index.SymbolHeading || sym.Anchor == "" {
8089
continue
8190
}
82-
if !strings.HasPrefix(strings.ToLower(sym.Anchor), prefixLower) {
91+
if !hasPrefixFold(sym.Anchor, prefixLower) {
8392
continue
8493
}
8594
sortPfx := "b"
@@ -103,15 +112,15 @@ func (s *Server) anchorItems(file, prefix string, idx *index.Index, sameFile boo
103112
func (s *Server) refLabelItems(file, prefix string, idx *index.Index) []completionItem {
104113
fe, ok := idx.File(file)
105114
if !ok {
106-
return []completionItem{}
115+
return nil
107116
}
108117
prefixLower := strings.ToLower(prefix)
109118
var items []completionItem
110119
for _, sym := range fe.Symbols {
111120
if sym.Kind != index.SymbolLinkRef {
112121
continue
113122
}
114-
if !strings.HasPrefix(strings.ToLower(sym.Anchor), prefixLower) {
123+
if !hasPrefixFold(sym.Anchor, prefixLower) {
115124
continue
116125
}
117126
items = append(items, completionItem{
@@ -128,12 +137,12 @@ func (s *Server) refLabelItems(file, prefix string, idx *index.Index) []completi
128137
func (s *Server) kindItems(prefix string) []completionItem {
129138
cfg, _, _ := s.snapshotConfig()
130139
if cfg == nil {
131-
return []completionItem{}
140+
return nil
132141
}
133142
prefixLower := strings.ToLower(prefix)
134143
var items []completionItem
135144
for k := range cfg.Kinds {
136-
if !strings.HasPrefix(strings.ToLower(k), prefixLower) {
145+
if !hasPrefixFold(k, prefixLower) {
137146
continue
138147
}
139148
items = append(items, completionItem{
@@ -168,7 +177,7 @@ func (s *Server) directivePathItems(rel, prefix string, idx *index.Index) []comp
168177
var items []completionItem
169178
for _, f := range files {
170179
relF := relFromDir(dir, f)
171-
if !strings.HasPrefix(strings.ToLower(relF), prefixLower) {
180+
if !hasPrefixFold(relF, prefixLower) {
172181
continue
173182
}
174183
label := relF

internal/lsp/symbols.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -459,7 +459,7 @@ func buildOutline(source []byte) []documentSymbol {
459459
idx.Update("buffer", source)
460460
fe, ok := idx.File("buffer")
461461
if !ok {
462-
return []documentSymbol{}
462+
return nil
463463
}
464464

465465
var fmKids []documentSymbol

internal/rules/concisenessscoring/classifier/model.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -470,7 +470,7 @@ func phraseMarker(phrase string) string {
470470

471471
func dedupeSorted(values []string) []string {
472472
if len(values) == 0 {
473-
return []string{}
473+
return nil
474474
}
475475
seen := map[string]struct{}{}
476476
out := make([]string, 0, len(values))

internal/rules/requiredstructure/rule.go

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1332,11 +1332,14 @@ func collectBodySyncPoints(
13321332
}
13331333
if currentHeading >= 0 && trimmed != "" {
13341334
fields := fieldinterp.Fields(trimmed)
1335-
for _, f := range fields {
1336-
syncPoints[currentHeading] = append(
1337-
syncPoints[currentHeading],
1338-
syncPoint{Field: f, InBody: true, BodyText: trimmed, compiled: buildFieldPattern(trimmed)},
1339-
)
1335+
if len(fields) > 0 {
1336+
compiled := buildFieldPattern(trimmed)
1337+
for _, f := range fields {
1338+
syncPoints[currentHeading] = append(
1339+
syncPoints[currentHeading],
1340+
syncPoint{Field: f, InBody: true, BodyText: trimmed, compiled: compiled},
1341+
)
1342+
}
13401343
}
13411344
}
13421345
}

0 commit comments

Comments
 (0)