mirror of https://github.com/golang/go.git
internal/lsp/source: reduce allocation in workspace-symbols
dynamicSymbolMatch is an allocation hotspot (9% of all bytes), because it allocates a 3-element []string that quickly becomes garbage. This change passes in an empty slice with spare capacity allowing the same array to be reused throughout the matchFile loop. BenchmarkSymbols on k8s shows -72% bytes, -88% allocs, -9% wall time. Change-Id: Id20c7cd649874a212e4d4c5f1aa095277b044a5b Reviewed-on: https://go-review.googlesource.com/c/tools/+/415500 TryBot-Result: Gopher Robot <gobot@golang.org> Run-TryBot: Alan Donovan <adonovan@google.com> gopls-CI: kokoro <noreply+kokoro@google.com> Reviewed-by: Robert Findley <rfindley@google.com>
This commit is contained in:
parent
7b04e8b59e
commit
f487f3623e
|
|
@ -83,17 +83,19 @@ type matcherFunc func(chunks []string) (int, float64)
|
|||
// []string{"myType.field"} or []string{"myType.", "field"}.
|
||||
//
|
||||
// See the comment for symbolCollector for more information.
|
||||
type symbolizer func(name string, pkg Metadata, m matcherFunc) ([]string, float64)
|
||||
//
|
||||
// The space argument is an empty slice with spare capacity that may be used
|
||||
// to allocate the result.
|
||||
type symbolizer func(space []string, name string, pkg Metadata, m matcherFunc) ([]string, float64)
|
||||
|
||||
func fullyQualifiedSymbolMatch(name string, pkg Metadata, matcher matcherFunc) ([]string, float64) {
|
||||
_, score := dynamicSymbolMatch(name, pkg, matcher)
|
||||
if score > 0 {
|
||||
return []string{pkg.PackagePath(), ".", name}, score
|
||||
func fullyQualifiedSymbolMatch(space []string, name string, pkg Metadata, matcher matcherFunc) ([]string, float64) {
|
||||
if _, score := dynamicSymbolMatch(space, name, pkg, matcher); score > 0 {
|
||||
return append(space, pkg.PackagePath(), ".", name), score
|
||||
}
|
||||
return nil, 0
|
||||
}
|
||||
|
||||
func dynamicSymbolMatch(name string, pkg Metadata, matcher matcherFunc) ([]string, float64) {
|
||||
func dynamicSymbolMatch(space []string, name string, pkg Metadata, matcher matcherFunc) ([]string, float64) {
|
||||
var score float64
|
||||
|
||||
endsInPkgName := strings.HasSuffix(pkg.PackagePath(), pkg.PackageName())
|
||||
|
|
@ -101,14 +103,14 @@ func dynamicSymbolMatch(name string, pkg Metadata, matcher matcherFunc) ([]strin
|
|||
// If the package path does not end in the package name, we need to check the
|
||||
// package-qualified symbol as an extra pass first.
|
||||
if !endsInPkgName {
|
||||
pkgQualified := []string{pkg.PackageName(), ".", name}
|
||||
pkgQualified := append(space, pkg.PackageName(), ".", name)
|
||||
idx, score := matcher(pkgQualified)
|
||||
nameStart := len(pkg.PackageName()) + 1
|
||||
if score > 0 {
|
||||
// If our match is contained entirely within the unqualified portion,
|
||||
// just return that.
|
||||
if idx >= nameStart {
|
||||
return []string{name}, score
|
||||
return append(space, name), score
|
||||
}
|
||||
// Lower the score for matches that include the package name.
|
||||
return pkgQualified, score * 0.8
|
||||
|
|
@ -116,13 +118,13 @@ func dynamicSymbolMatch(name string, pkg Metadata, matcher matcherFunc) ([]strin
|
|||
}
|
||||
|
||||
// Now try matching the fully qualified symbol.
|
||||
fullyQualified := []string{pkg.PackagePath(), ".", name}
|
||||
fullyQualified := append(space, pkg.PackagePath(), ".", name)
|
||||
idx, score := matcher(fullyQualified)
|
||||
|
||||
// As above, check if we matched just the unqualified symbol name.
|
||||
nameStart := len(pkg.PackagePath()) + 1
|
||||
if idx >= nameStart {
|
||||
return []string{name}, score
|
||||
return append(space, name), score
|
||||
}
|
||||
|
||||
// If our package path ends in the package name, we'll have skipped the
|
||||
|
|
@ -131,7 +133,7 @@ func dynamicSymbolMatch(name string, pkg Metadata, matcher matcherFunc) ([]strin
|
|||
if endsInPkgName && idx >= 0 {
|
||||
pkgStart := len(pkg.PackagePath()) - len(pkg.PackageName())
|
||||
if idx >= pkgStart {
|
||||
return []string{pkg.PackageName(), ".", name}, score
|
||||
return append(space, pkg.PackageName(), ".", name), score
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -140,8 +142,8 @@ func dynamicSymbolMatch(name string, pkg Metadata, matcher matcherFunc) ([]strin
|
|||
return fullyQualified, score * 0.6
|
||||
}
|
||||
|
||||
func packageSymbolMatch(name string, pkg Metadata, matcher matcherFunc) ([]string, float64) {
|
||||
qualified := []string{pkg.PackageName(), ".", name}
|
||||
func packageSymbolMatch(space []string, name string, pkg Metadata, matcher matcherFunc) ([]string, float64) {
|
||||
qualified := append(space, pkg.PackageName(), ".", name)
|
||||
if _, s := matcher(qualified); s > 0 {
|
||||
return qualified, s
|
||||
}
|
||||
|
|
@ -387,8 +389,9 @@ type symbolFile struct {
|
|||
|
||||
// matchFile scans a symbol file and adds matching symbols to the store.
|
||||
func matchFile(store *symbolStore, symbolizer symbolizer, matcher matcherFunc, roots []string, i symbolFile) {
|
||||
space := make([]string, 0, 3)
|
||||
for _, sym := range i.syms {
|
||||
symbolParts, score := symbolizer(sym.Name, i.md, matcher)
|
||||
symbolParts, score := symbolizer(space, sym.Name, i.md, matcher)
|
||||
|
||||
// Check if the score is too low before applying any downranking.
|
||||
if store.tooLow(score) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue