]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/go: always track visited packages in setPGOProfilePath
authorMichael Pratt <mpratt@google.com>
Fri, 26 May 2023 19:49:22 +0000 (15:49 -0400)
committerGopher Robot <gobot@golang.org>
Sat, 27 May 2023 00:39:39 +0000 (00:39 +0000)
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>

src/cmd/go/internal/load/pkg.go

index 191118b1e7e357a5874dc156e7290c71d8c90d51..a66df86f5cc286120867935a3f1c5ea1f36b0e30 100644 (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)