Skip to content

Commit d3fe2f5

Browse files
Pre-allocate parsedPatterns and cache some calculations (#371)
1 parent 30a2e24 commit d3fe2f5

File tree

3 files changed

+45
-11
lines changed

3 files changed

+45
-11
lines changed

internal/compiler/module/cache.go

+5
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@ type caches struct {
1818
typeReferenceDirectiveCache *resolutionCache[*ResolvedTypeReferenceDirective]
1919
packageJsonInfoCache *packagejson.InfoCache
2020
resolvedTypeReferenceDirectiveLookupLocations map[*ResolvedTypeReferenceDirective]*LookupLocations
21+
22+
// Cached representation for `core.CompilerOptions.paths`.
23+
// Doesn't handle other path patterns like in `typesVersions`.
24+
parsedPatternsForPathsOnce sync.Once
25+
parsedPatternsForPaths *parsedPatterns
2126
}
2227

2328
func newCaches(

internal/compiler/module/resolver.go

+33-11
Original file line numberDiff line numberDiff line change
@@ -1030,7 +1030,7 @@ func (r *resolutionState) tryLoadModuleUsingPathsIfEligible() *resolved {
10301030
return continueSearching()
10311031
}
10321032
baseDirectory := getPathsBasePath(r.compilerOptions, r.resolver.host.GetCurrentDirectory())
1033-
pathPatterns := tryParsePatterns(r.compilerOptions.Paths)
1033+
pathPatterns := r.resolver.getParsedPatternsForPaths()
10341034
return r.tryLoadModuleUsingPaths(
10351035
r.extensions,
10361036
r.name,
@@ -1044,7 +1044,7 @@ func (r *resolutionState) tryLoadModuleUsingPathsIfEligible() *resolved {
10441044
)
10451045
}
10461046

1047-
func (r *resolutionState) tryLoadModuleUsingPaths(extensions extensions, moduleName string, containingDirectory string, paths *collections.OrderedMap[string, []string], pathPatterns parsedPatterns, loader resolutionKindSpecificLoader, onlyRecordFailures bool) *resolved {
1047+
func (r *resolutionState) tryLoadModuleUsingPaths(extensions extensions, moduleName string, containingDirectory string, paths *collections.OrderedMap[string, []string], pathPatterns *parsedPatterns, loader resolutionKindSpecificLoader, onlyRecordFailures bool) *resolved {
10481048
if matchedPattern := matchPatternOrExact(pathPatterns, moduleName); matchedPattern.IsValid() {
10491049
matchedStar := matchedPattern.MatchedText(moduleName)
10501050
if r.resolver.traceEnabled() {
@@ -1697,16 +1697,38 @@ func getPathsBasePath(options *core.CompilerOptions, currentDirectory string) st
16971697
}
16981698

16991699
type parsedPatterns struct {
1700-
matchableStringSet collections.OrderedSet[string]
1700+
matchableStringSet core.Set[string]
17011701
patterns []core.Pattern
17021702
}
17031703

1704-
func tryParsePatterns(paths *collections.OrderedMap[string, []string]) parsedPatterns {
1705-
// !!! TS has a weakmap cache
1706-
// We could store a cache on Resolver, but maybe we can wait and profile
1707-
matchableStringSet := collections.OrderedSet[string]{}
1708-
patterns := make([]core.Pattern, 0, paths.Size())
1709-
for path := range paths.Keys() {
1704+
func (r *Resolver) getParsedPatternsForPaths() *parsedPatterns {
1705+
r.parsedPatternsForPathsOnce.Do(func() {
1706+
r.parsedPatternsForPaths = tryParsePatterns(r.compilerOptions.Paths)
1707+
})
1708+
return r.parsedPatternsForPaths
1709+
}
1710+
1711+
func tryParsePatterns(pathMappings *collections.OrderedMap[string, []string]) *parsedPatterns {
1712+
paths := pathMappings.Keys()
1713+
1714+
numPatterns := 0
1715+
for path := range paths {
1716+
if pattern := core.TryParsePattern(path); pattern.IsValid() && pattern.StarIndex == -1 {
1717+
numPatterns++
1718+
}
1719+
}
1720+
numMatchables := pathMappings.Size() - numPatterns
1721+
1722+
var patterns []core.Pattern
1723+
var matchableStringSet core.Set[string]
1724+
if numPatterns != 0 {
1725+
patterns = make([]core.Pattern, 0, numPatterns)
1726+
}
1727+
if numMatchables != 0 {
1728+
matchableStringSet = *core.NewSetWithSizeHint[string](numMatchables)
1729+
}
1730+
1731+
for path := range paths {
17101732
if pattern := core.TryParsePattern(path); pattern.IsValid() {
17111733
if pattern.StarIndex == -1 {
17121734
matchableStringSet.Add(path)
@@ -1715,13 +1737,13 @@ func tryParsePatterns(paths *collections.OrderedMap[string, []string]) parsedPat
17151737
}
17161738
}
17171739
}
1718-
return parsedPatterns{
1740+
return &parsedPatterns{
17191741
matchableStringSet: matchableStringSet,
17201742
patterns: patterns,
17211743
}
17221744
}
17231745

1724-
func matchPatternOrExact(patterns parsedPatterns, candidate string) core.Pattern {
1746+
func matchPatternOrExact(patterns *parsedPatterns, candidate string) core.Pattern {
17251747
if patterns.matchableStringSet.Has(candidate) {
17261748
return core.Pattern{
17271749
Text: candidate,

internal/core/set.go

+7
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,13 @@ type Set[T comparable] struct {
44
M map[T]struct{}
55
}
66

7+
// NewSetWithSizeHint creates a new Set with a hint for the number of elements it will contain.
8+
func NewSetWithSizeHint[T comparable](hint int) *Set[T] {
9+
return &Set[T]{
10+
M: make(map[T]struct{}, hint),
11+
}
12+
}
13+
714
func (s *Set[T]) Has(key T) bool {
815
_, ok := s.M[key]
916
return ok

0 commit comments

Comments
 (0)