зеркало из https://github.com/golang/tools.git
compilebench: add a linker benchmark
This links cmd/compile, which is the largest binary in GOROOT. Unfortunately, this can't measure the linker's allocation metrics prior to CL 176057 because the fix for golang/go#18641 was applied to the compiler but not the linker. Change-Id: Ia44d80f1d727c1608cedaa4b8ad2a05903774875 Reviewed-on: https://go-review.googlesource.com/c/tools/+/175801 Run-TryBot: Austin Clements <austin@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Russ Cox <rsc@golang.org> Reviewed-by: Cherry Zhang <cherryyz@google.com>
This commit is contained in:
Родитель
eeb76a0c47
Коммит
60140f0909
|
@ -22,6 +22,12 @@
|
|||
// -compileflags 'list'
|
||||
// Pass the space-separated list of flags to the compilation.
|
||||
//
|
||||
// -link exe
|
||||
// Use exe as the path to the cmd/link binary.
|
||||
//
|
||||
// -linkflags 'list'
|
||||
// Pass the space-separated list of flags to the linker.
|
||||
//
|
||||
// -count n
|
||||
// Run each benchmark n times (default 1).
|
||||
//
|
||||
|
@ -90,6 +96,7 @@ import (
|
|||
var (
|
||||
goroot string
|
||||
compiler string
|
||||
linker string
|
||||
runRE *regexp.Regexp
|
||||
is6g bool
|
||||
)
|
||||
|
@ -100,6 +107,8 @@ var (
|
|||
flagObj = flag.Bool("obj", false, "report object file stats")
|
||||
flagCompiler = flag.String("compile", "", "use `exe` as the cmd/compile binary")
|
||||
flagCompilerFlags = flag.String("compileflags", "", "additional `flags` to pass to compile")
|
||||
flagLinker = flag.String("link", "", "use `exe` as the cmd/link binary")
|
||||
flagLinkerFlags = flag.String("linkflags", "", "additional `flags` to pass to link")
|
||||
flagRun = flag.String("run", "", "run benchmarks matching `regexp`")
|
||||
flagCount = flag.Int("count", 1, "run benchmarks `n` times")
|
||||
flagCpuprofile = flag.String("cpuprofile", "", "write CPU profile to `file`")
|
||||
|
@ -130,6 +139,7 @@ var tests = []test{
|
|||
{"BenchmarkReflect", compile{"reflect"}},
|
||||
{"BenchmarkTar", compile{"archive/tar"}},
|
||||
{"BenchmarkXML", compile{"encoding/xml"}},
|
||||
{"BenchmarkLinkCompiler", link{"cmd/compile"}},
|
||||
{"BenchmarkStdCmd", goBuild{[]string{"std", "cmd"}}},
|
||||
{"BenchmarkHelloSize", size{"$GOROOT/test/helloworld.go", false}},
|
||||
{"BenchmarkCmdGoSize", size{"cmd/go", true}},
|
||||
|
@ -160,16 +170,16 @@ func main() {
|
|||
|
||||
compiler = *flagCompiler
|
||||
if compiler == "" {
|
||||
out, err := exec.Command(*flagGoCmd, "tool", "-n", "compile").CombinedOutput()
|
||||
if err != nil {
|
||||
out, err = exec.Command(*flagGoCmd, "tool", "-n", "6g").CombinedOutput()
|
||||
var foundTool string
|
||||
foundTool, compiler = toolPath("compile", "6g")
|
||||
if foundTool == "6g" {
|
||||
is6g = true
|
||||
if err != nil {
|
||||
out, err = exec.Command(*flagGoCmd, "tool", "-n", "compile").CombinedOutput()
|
||||
log.Fatalf("go tool -n compiler: %v\n%s", err, out)
|
||||
}
|
||||
}
|
||||
compiler = strings.TrimSpace(string(out))
|
||||
}
|
||||
|
||||
linker = *flagLinker
|
||||
if linker == "" && !is6g { // TODO: Support 6l
|
||||
_, linker = toolPath("link")
|
||||
}
|
||||
|
||||
if is6g {
|
||||
|
@ -190,6 +200,7 @@ func main() {
|
|||
if *flagPackage != "" {
|
||||
tests = []test{
|
||||
{"BenchmarkPkg", compile{*flagPackage}},
|
||||
{"BenchmarkPkgLink", link{*flagPackage}},
|
||||
}
|
||||
runRE = nil
|
||||
}
|
||||
|
@ -208,6 +219,39 @@ func main() {
|
|||
}
|
||||
}
|
||||
|
||||
func toolPath(names ...string) (found, path string) {
|
||||
var out1 []byte
|
||||
var err1 error
|
||||
for i, name := range names {
|
||||
out, err := exec.Command(*flagGoCmd, "tool", "-n", name).CombinedOutput()
|
||||
if err == nil {
|
||||
return name, strings.TrimSpace(string(out))
|
||||
}
|
||||
if i == 0 {
|
||||
out1, err1 = out, err
|
||||
}
|
||||
}
|
||||
log.Fatalf("go tool -n %s: %v\n%s", names[0], err1, out1)
|
||||
return "", ""
|
||||
}
|
||||
|
||||
type Pkg struct {
|
||||
Dir string
|
||||
GoFiles []string
|
||||
}
|
||||
|
||||
func goList(dir string) (*Pkg, error) {
|
||||
var pkg Pkg
|
||||
out, err := exec.Command(*flagGoCmd, "list", "-json", dir).Output()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("go list -json %s: %v\n", dir, err)
|
||||
}
|
||||
if err := json.Unmarshal(out, &pkg); err != nil {
|
||||
return nil, fmt.Errorf("go list -json %s: unmarshal: %v", dir, err)
|
||||
}
|
||||
return &pkg, nil
|
||||
}
|
||||
|
||||
func runCmd(name string, cmd *exec.Cmd) error {
|
||||
start := time.Now()
|
||||
out, err := cmd.CombinedOutput()
|
||||
|
@ -286,16 +330,9 @@ func (c compile) run(name string, count int) error {
|
|||
}
|
||||
|
||||
// Find dir and source file list.
|
||||
var pkg struct {
|
||||
Dir string
|
||||
GoFiles []string
|
||||
}
|
||||
out, err = exec.Command(*flagGoCmd, "list", "-json", c.dir).Output()
|
||||
pkg, err := goList(c.dir)
|
||||
if err != nil {
|
||||
return fmt.Errorf("go list -json %s: %v\n", c.dir, err)
|
||||
}
|
||||
if err := json.Unmarshal(out, &pkg); err != nil {
|
||||
return fmt.Errorf("go list -json %s: unmarshal: %v", c.dir, err)
|
||||
return err
|
||||
}
|
||||
|
||||
args := []string{"-o", "_compilebench_.o"}
|
||||
|
@ -324,6 +361,52 @@ func (c compile) run(name string, count int) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
type link struct{ dir string }
|
||||
|
||||
func (link) long() bool { return false }
|
||||
|
||||
func (r link) run(name string, count int) error {
|
||||
if linker == "" {
|
||||
// No linker. Skip the test.
|
||||
return nil
|
||||
}
|
||||
|
||||
// Build dependencies.
|
||||
out, err := exec.Command(*flagGoCmd, "build", "-i", "-o", "/dev/null", r.dir).CombinedOutput()
|
||||
if err != nil {
|
||||
return fmt.Errorf("go build -i %s: %v\n%s", r.dir, err, out)
|
||||
}
|
||||
|
||||
// Build the main package.
|
||||
pkg, err := goList(r.dir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
args := []string{"-o", "_compilebench_.o"}
|
||||
args = append(args, pkg.GoFiles...)
|
||||
cmd := exec.Command(compiler, args...)
|
||||
cmd.Dir = pkg.Dir
|
||||
cmd.Stdout = os.Stderr
|
||||
cmd.Stderr = os.Stderr
|
||||
err = cmd.Run()
|
||||
if err != nil {
|
||||
return fmt.Errorf("compiling: %v", err)
|
||||
}
|
||||
defer os.Remove(pkg.Dir + "/_compilebench_.o")
|
||||
|
||||
// Link the main package.
|
||||
args = []string{"-o", "_compilebench_.exe"}
|
||||
args = append(args, strings.Fields(*flagLinkerFlags)...)
|
||||
args = append(args, "_compilebench_.o")
|
||||
if err := runBuildCmd(name, count, pkg.Dir, linker, args); err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Println()
|
||||
defer os.Remove(pkg.Dir + "/_compilebench_.exe")
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// runBuildCmd runs "tool args..." in dir, measures standard build
|
||||
// tool metrics, and prints a benchmark line. The caller may print
|
||||
// additional metrics and then must print a newline.
|
||||
|
|
Загрузка…
Ссылка в новой задаче