1
0
mirror of https://github.com/golang/go synced 2024-11-24 16:20:13 -07:00

cmd/go: add benchmark for go list -m

Updates #63136
This commit is contained in:
goto1134 2024-08-24 09:57:02 +02:00
parent 96d8ff00c2
commit e9044a1e65
No known key found for this signature in database
4 changed files with 224 additions and 0 deletions

190
src/cmd/go/list_test.go Normal file
View File

@ -0,0 +1,190 @@
// Copyright 2024 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main_test
import (
"internal/testenv"
"io"
"net/http"
"os"
"path/filepath"
"strings"
"sync/atomic"
"testing"
)
var modulesForTest = []struct {
name string
testDataFolder string
url string
dependenciesToStrip []string
}{
{
name: "Empty",
testDataFolder: "empty",
},
{
name: "Cmd",
testDataFolder: "cmd",
},
{
name: "K8S",
testDataFolder: "k8s",
url: "https://raw.githubusercontent.com/kubernetes/kubernetes/b33ef18bdfa62d3975f2c72743373f1d69740b99",
dependenciesToStrip: []string{
"k8s.io/api",
"k8s.io/apiextensions-apiserver",
"k8s.io/apimachinery",
"k8s.io/apiserver",
"k8s.io/cli-runtime",
"k8s.io/client-go",
"k8s.io/cloud-provider",
"k8s.io/cluster-bootstrap",
"k8s.io/code-generator",
"k8s.io/component-base",
"k8s.io/component-helpers",
"k8s.io/controller-manager",
"k8s.io/cri-api",
"k8s.io/cri-client",
"k8s.io/csi-translation-lib",
"k8s.io/dynamic-resource-allocation",
"k8s.io/endpointslice",
"k8s.io/kms",
"k8s.io/kube-aggregator",
"k8s.io/kube-controller-manager",
"k8s.io/kube-proxy",
"k8s.io/kube-scheduler",
"k8s.io/kubectl",
"k8s.io/kubelet",
"k8s.io/metrics",
"k8s.io/mount-utils",
"k8s.io/pod-security-admission",
"k8s.io/sample-apiserver",
"k8s.io/sample-cli-plugin",
"k8s.io/sample-controller",
},
},
}
func BenchmarkListModules(b *testing.B) {
testenv.MustHaveExec(b)
gotool, err := testenv.GoTool()
if err != nil {
b.Fatal(err)
}
tempDir := b.TempDir()
if err := prepareTestModules(tempDir); err != nil {
b.Fatal(err)
}
b.ResetTimer()
for _, m := range modulesForTest {
// Do not run in parallel. GOPROXY rate limits may affect parallel executions.
b.Run(m.name, func(b *testing.B) {
// We collect extra metrics.
var n, userTime, systemTime int64
modDir := filepath.Join(tempDir, m.testDataFolder, "go.mod")
for i := 0; i < b.N; i++ {
cmd := testenv.Command(b, gotool, "list", "-m", "-modfile="+modDir, "-mod=readonly", "all")
// Guarantees clean module cache for every execution.
gopath := b.TempDir()
cmd.Env = append(cmd.Env, "GOPATH="+gopath)
if err := cmd.Run(); err != nil {
b.Fatal(err)
}
atomic.AddInt64(&n, 1)
atomic.AddInt64(&userTime, int64(cmd.ProcessState.UserTime()))
atomic.AddInt64(&systemTime, int64(cmd.ProcessState.SystemTime()))
}
b.ReportMetric(float64(userTime)/float64(n), "user-ns/op")
b.ReportMetric(float64(systemTime)/float64(n), "sys-ns/op")
})
}
}
func prepareTestModules(tempDir string) error {
err := os.CopyFS(tempDir, os.DirFS(filepath.Join("testdata", "list")))
if err != nil {
return err
}
for _, m := range modulesForTest {
if m.url != "" {
modulePath := filepath.Join(tempDir, m.testDataFolder)
if err := downloadModule(modulePath, m.url, m.dependenciesToStrip); err != nil {
return err
}
}
}
return nil
}
func downloadModule(modulePath string, url string, dependenciesToStrip []string) error {
if err := os.Mkdir(modulePath, 0755); err != nil {
return err
}
sumText, err := fetchText(url + "/go.sum")
if err != nil {
return err
}
if err := writeFile(filepath.Join(modulePath, "go.sum"), sumText); err != nil {
return err
}
modText, err := fetchText(url + "/go.mod")
if err != nil {
return err
}
strippedModText := stripDependencies(modText, dependenciesToStrip)
return writeFile(filepath.Join(modulePath, "go.mod"), strippedModText)
}
func stripDependencies(goModText string, dependenciesToStrip []string) string {
var filteredLines []string
lines := strings.Split(goModText, "\n")
for _, line := range lines {
if !containsAny(line, dependenciesToStrip) {
filteredLines = append(filteredLines, line)
}
}
filteredText := strings.Join(filteredLines, "\n")
return filteredText
}
func containsAny(text string, options []string) bool {
for _, option := range options {
if strings.Contains(text, option) {
return true
}
}
return false
}
func writeFile(filePath, content string) error {
out, err := os.Create(filePath)
if err != nil {
return err
}
defer out.Close()
_, err = io.WriteString(out, content)
return err
}
func fetchText(url string) (string, error) {
resp, err := http.Get(url)
if err != nil {
return "", err
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
return string(body), err
}

15
src/cmd/go/testdata/list/cmd/go.mod vendored Normal file
View File

@ -0,0 +1,15 @@
module cmd
go 1.22
require (
github.com/google/pprof v0.0.0-20230811205829-9131a7e9cc17
golang.org/x/arch v0.6.0
golang.org/x/mod v0.14.0
golang.org/x/sync v0.5.0
golang.org/x/sys v0.15.0
golang.org/x/term v0.15.0
golang.org/x/tools v0.16.2-0.20231218185909-83bceaf2424d
)
require github.com/ianlancetaylor/demangle v0.0.0-20230524184225-eabc099b10ab // indirect

16
src/cmd/go/testdata/list/cmd/go.sum vendored Normal file
View File

@ -0,0 +1,16 @@
github.com/google/pprof v0.0.0-20230811205829-9131a7e9cc17 h1:0h35ESZ02+hN/MFZb7XZOXg+Rl9+Rk8fBIf5YLws9gA=
github.com/google/pprof v0.0.0-20230811205829-9131a7e9cc17/go.mod h1:Jh3hGz2jkYak8qXPD19ryItVnUgpgeqzdkY/D0EaeuA=
github.com/ianlancetaylor/demangle v0.0.0-20230524184225-eabc099b10ab h1:BA4a7pe6ZTd9F8kXETBoijjFJ/ntaa//1wiH9BZu4zU=
github.com/ianlancetaylor/demangle v0.0.0-20230524184225-eabc099b10ab/go.mod h1:gx7rwoVhcfuVKG5uya9Hs3Sxj7EIvldVofAWIUtGouw=
golang.org/x/arch v0.6.0 h1:S0JTfE48HbRj80+4tbvZDYsJ3tGv6BUU3XxyZ7CirAc=
golang.org/x/arch v0.6.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0=
golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE=
golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4=
golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
golang.org/x/tools v0.16.2-0.20231218185909-83bceaf2424d h1:9YOyUBubvYqtjjtZBnI62JT9/QB9jfPwOQ7xLeyuOIU=
golang.org/x/tools v0.16.2-0.20231218185909-83bceaf2424d/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0=

3
src/cmd/go/testdata/list/empty/go.mod vendored Normal file
View File

@ -0,0 +1,3 @@
module empty
go 1.22