From bfe4fc1341e8f7fcc13e70166d37b2b8853b6a71 Mon Sep 17 00:00:00 2001 From: Gabriel Castro Date: Mon, 8 Dec 2025 18:11:34 -0500 Subject: [PATCH 1/3] Fix perfromance when there's lots of error DiagnosticsCollection#Add() used InsertSort, this causes a ton of memcopys on every error. This is O(n) for every error. Instead I moved the sort to lazily happen just before each GetDiagnostics call this is not only O(nlogn), but gets happen way less often than Inserts --- internal/ast/diagnostic.go | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/internal/ast/diagnostic.go b/internal/ast/diagnostic.go index 7757501881..6f04565e7c 100644 --- a/internal/ast/diagnostic.go +++ b/internal/ast/diagnostic.go @@ -123,7 +123,9 @@ func NewCompilerDiagnostic(message *diagnostics.Message, args ...any) *Diagnosti type DiagnosticsCollection struct { fileDiagnostics map[string][]*Diagnostic + fileDiagnosticsSorted map[string]bool nonFileDiagnostics []*Diagnostic + nonFileDiagnosticsSorted bool } func (c *DiagnosticsCollection) Add(diagnostic *Diagnostic) { @@ -132,18 +134,23 @@ func (c *DiagnosticsCollection) Add(diagnostic *Diagnostic) { if c.fileDiagnostics == nil { c.fileDiagnostics = make(map[string][]*Diagnostic) } - c.fileDiagnostics[fileName] = core.InsertSorted(c.fileDiagnostics[fileName], diagnostic, CompareDiagnostics) + if c.fileDiagnosticsSorted == nil { + c.fileDiagnosticsSorted = make(map[string]bool) + } + c.fileDiagnostics[fileName] = append(c.fileDiagnostics[fileName], diagnostic) + c.fileDiagnosticsSorted[fileName] = false } else { - c.nonFileDiagnostics = core.InsertSorted(c.nonFileDiagnostics, diagnostic, CompareDiagnostics) + c.nonFileDiagnostics = append(c.nonFileDiagnostics, diagnostic) + c.nonFileDiagnosticsSorted = false } } func (c *DiagnosticsCollection) Lookup(diagnostic *Diagnostic) *Diagnostic { var diagnostics []*Diagnostic if diagnostic.File() != nil { - diagnostics = c.fileDiagnostics[diagnostic.File().FileName()] + diagnostics = c.GetDiagnosticsForFile(diagnostic.File().FileName()) } else { - diagnostics = c.nonFileDiagnostics + diagnostics = c.GetGlobalDiagnostics() } if i, ok := slices.BinarySearchFunc(diagnostics, diagnostic, CompareDiagnostics); ok { return diagnostics[i] @@ -152,10 +159,21 @@ func (c *DiagnosticsCollection) Lookup(diagnostic *Diagnostic) *Diagnostic { } func (c *DiagnosticsCollection) GetGlobalDiagnostics() []*Diagnostic { + if (!c.nonFileDiagnosticsSorted) { + slices.SortStableFunc(c.nonFileDiagnostics, CompareDiagnostics) + c.nonFileDiagnosticsSorted = true + } return c.nonFileDiagnostics } func (c *DiagnosticsCollection) GetDiagnosticsForFile(fileName string) []*Diagnostic { + if c.fileDiagnosticsSorted == nil { + c.fileDiagnosticsSorted = make(map[string]bool) + } + if (!c.fileDiagnosticsSorted[fileName]) { + slices.SortStableFunc(c.fileDiagnostics[fileName], CompareDiagnostics) + c.fileDiagnosticsSorted[fileName] = true + } return c.fileDiagnostics[fileName] } From a19924e86e3e8998917576d97f0a7294c39a62a1 Mon Sep 17 00:00:00 2001 From: Gabriel Castro Date: Mon, 8 Dec 2025 18:23:13 -0500 Subject: [PATCH 2/3] fmt --- internal/ast/diagnostic.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/internal/ast/diagnostic.go b/internal/ast/diagnostic.go index 6f04565e7c..bb32e0f7b7 100644 --- a/internal/ast/diagnostic.go +++ b/internal/ast/diagnostic.go @@ -122,9 +122,9 @@ func NewCompilerDiagnostic(message *diagnostics.Message, args ...any) *Diagnosti } type DiagnosticsCollection struct { - fileDiagnostics map[string][]*Diagnostic - fileDiagnosticsSorted map[string]bool - nonFileDiagnostics []*Diagnostic + fileDiagnostics map[string][]*Diagnostic + fileDiagnosticsSorted map[string]bool + nonFileDiagnostics []*Diagnostic nonFileDiagnosticsSorted bool } @@ -135,7 +135,7 @@ func (c *DiagnosticsCollection) Add(diagnostic *Diagnostic) { c.fileDiagnostics = make(map[string][]*Diagnostic) } if c.fileDiagnosticsSorted == nil { - c.fileDiagnosticsSorted = make(map[string]bool) + c.fileDiagnosticsSorted = make(map[string]bool) } c.fileDiagnostics[fileName] = append(c.fileDiagnostics[fileName], diagnostic) c.fileDiagnosticsSorted[fileName] = false @@ -159,7 +159,7 @@ func (c *DiagnosticsCollection) Lookup(diagnostic *Diagnostic) *Diagnostic { } func (c *DiagnosticsCollection) GetGlobalDiagnostics() []*Diagnostic { - if (!c.nonFileDiagnosticsSorted) { + if !c.nonFileDiagnosticsSorted { slices.SortStableFunc(c.nonFileDiagnostics, CompareDiagnostics) c.nonFileDiagnosticsSorted = true } @@ -170,7 +170,7 @@ func (c *DiagnosticsCollection) GetDiagnosticsForFile(fileName string) []*Diagno if c.fileDiagnosticsSorted == nil { c.fileDiagnosticsSorted = make(map[string]bool) } - if (!c.fileDiagnosticsSorted[fileName]) { + if !c.fileDiagnosticsSorted[fileName] { slices.SortStableFunc(c.fileDiagnostics[fileName], CompareDiagnostics) c.fileDiagnosticsSorted[fileName] = true } From 60fc328e3fedf46ab26a03bfca231d11529a5d54 Mon Sep 17 00:00:00 2001 From: Gabriel Castro Date: Tue, 9 Dec 2025 00:01:10 -0500 Subject: [PATCH 3/3] use collections.Set --- internal/ast/diagnostic.go | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/internal/ast/diagnostic.go b/internal/ast/diagnostic.go index bb32e0f7b7..692a2fcc46 100644 --- a/internal/ast/diagnostic.go +++ b/internal/ast/diagnostic.go @@ -5,6 +5,7 @@ import ( "slices" "strings" + "github.com/microsoft/typescript-go/internal/collections" "github.com/microsoft/typescript-go/internal/core" "github.com/microsoft/typescript-go/internal/diagnostics" ) @@ -123,7 +124,7 @@ func NewCompilerDiagnostic(message *diagnostics.Message, args ...any) *Diagnosti type DiagnosticsCollection struct { fileDiagnostics map[string][]*Diagnostic - fileDiagnosticsSorted map[string]bool + fileDiagnosticsSorted collections.Set[string] nonFileDiagnostics []*Diagnostic nonFileDiagnosticsSorted bool } @@ -134,11 +135,8 @@ func (c *DiagnosticsCollection) Add(diagnostic *Diagnostic) { if c.fileDiagnostics == nil { c.fileDiagnostics = make(map[string][]*Diagnostic) } - if c.fileDiagnosticsSorted == nil { - c.fileDiagnosticsSorted = make(map[string]bool) - } c.fileDiagnostics[fileName] = append(c.fileDiagnostics[fileName], diagnostic) - c.fileDiagnosticsSorted[fileName] = false + c.fileDiagnosticsSorted.Delete(fileName) } else { c.nonFileDiagnostics = append(c.nonFileDiagnostics, diagnostic) c.nonFileDiagnosticsSorted = false @@ -167,12 +165,9 @@ func (c *DiagnosticsCollection) GetGlobalDiagnostics() []*Diagnostic { } func (c *DiagnosticsCollection) GetDiagnosticsForFile(fileName string) []*Diagnostic { - if c.fileDiagnosticsSorted == nil { - c.fileDiagnosticsSorted = make(map[string]bool) - } - if !c.fileDiagnosticsSorted[fileName] { + if !c.fileDiagnosticsSorted.Has(fileName) { slices.SortStableFunc(c.fileDiagnostics[fileName], CompareDiagnostics) - c.fileDiagnosticsSorted[fileName] = true + c.fileDiagnosticsSorted.Add(fileName) } return c.fileDiagnostics[fileName] }