cmd/go: always track visited packages in setPGOProfilePath

Currently we only track visited (copied) packages when a copy is
required. When a copy is not required, we will rewalk each package's
entire dependency graph every time we see it, which is terribly
inefficient.

Pull the visited package check up a level so that we visit packages only
once regardless of how many times they are visited.

Fixes #60455.
Fixes #60428.

Change-Id: I4e9b31eeeaa170db650c461a5de2ca984b9aba0f
Reviewed-on: https://go-review.googlesource.com/c/go/+/498735
Run-TryBot: Bryan Mills <bcmills@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Bryan Mills <bcmills@google.com>
Auto-Submit: Michael Pratt <mpratt@google.com>
This commit is contained in:
Michael Pratt 2023-05-26 15:49:22 -04:00 committed by Gopher Robot
parent 6e248b8ff2
commit 3824d3d71e
1 changed files with 12 additions and 6 deletions

View File

@ -2950,17 +2950,21 @@ func setPGOProfilePath(pkgs []*Package) {
continue // no profile
}
copied := make(map[*Package]*Package)
// Packages already visited. The value should replace
// the key, as it may be a forked copy of the original
// Package.
visited := make(map[*Package]*Package)
var split func(p *Package) *Package
split = func(p *Package) *Package {
if p1 := visited[p]; p1 != nil {
return p1
}
if len(pkgs) > 1 && p != pmain {
// Make a copy, then attach profile.
// No need to copy if there is only one root package (we can
// attach profile directly in-place).
// Also no need to copy the main package.
if p1 := copied[p]; p1 != nil {
return p1
}
if p.Internal.PGOProfile != "" {
panic("setPGOProfilePath: already have profile")
}
@ -2969,9 +2973,11 @@ func setPGOProfilePath(pkgs []*Package) {
// Unalias the Internal.Imports slice, which is we're going to
// modify. We don't copy other slices as we don't change them.
p1.Internal.Imports = slices.Clone(p.Internal.Imports)
copied[p] = p1
p1.Internal.ForMain = pmain.ImportPath
visited[p] = p1
p = p1
p.Internal.ForMain = pmain.ImportPath
} else {
visited[p] = p
}
p.Internal.PGOProfile = file
updateBuildInfo(p, file)