internal/gcimporter: optimize dependency lookup

The old code based on packages.Visit traversed in a
deterministic order, and didn't stop when it found its
target (the 'return false' only prunes that subtree).
This CL replaces it with a precomputation of the
PkgPath-to-*Package mapping.

The performance difference is small for this test but
it nearly dominates on a larger input (e.g. k8s).
Example code shouldn't steer users into asymptotic traps.

Change-Id: I19f4fc2c25da3d2ae00090704df30a54d8516bf5
Reviewed-on: https://go-review.googlesource.com/c/tools/+/447958
gopls-CI: kokoro <noreply+kokoro@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Alan Donovan <adonovan@google.com>
Reviewed-by: Robert Findley <rfindley@google.com>
This commit is contained in:
Alan Donovan 2022-11-04 15:23:06 -04:00
parent 39c2fd8bff
commit 3c8152e28a
1 changed files with 19 additions and 10 deletions

View File

@ -89,6 +89,23 @@ func typecheck(t *testing.T, ppkg *packages.Package) {
}
// Inv: all files were successfully parsed.
// Build map of dependencies by package path.
// (We don't compute this mapping for the entire
// packages graph because it is not globally consistent.)
depsByPkgPath := make(map[string]*packages.Package)
{
var visit func(*packages.Package)
visit = func(pkg *packages.Package) {
if depsByPkgPath[pkg.PkgPath] == nil {
depsByPkgPath[pkg.PkgPath] = pkg
for path := range pkg.Imports {
visit(pkg.Imports[path])
}
}
}
visit(ppkg)
}
// importer state
var (
insert func(p *types.Package, name string)
@ -100,16 +117,8 @@ func typecheck(t *testing.T, ppkg *packages.Package) {
return gcimporter.IImportShallow(fset, importMap, data, imp.PkgPath, insert)
}
insert = func(p *types.Package, name string) {
// Hunt for p among the transitive dependencies (inefficient).
var imp *packages.Package
packages.Visit([]*packages.Package{ppkg}, func(q *packages.Package) bool {
if q.PkgPath == p.Path() {
imp = q
return false
}
return true
}, nil)
if imp == nil {
imp, ok := depsByPkgPath[p.Path()]
if !ok {
t.Fatalf("can't find dependency: %q", p.Path())
}
imported, err := loadFromExportData(imp)