6060// today they write only the profile for the last benchmark executed.
6161//
6262// The default memory profiling rate is one profile sample per 512 kB
63- // allocated (see `` go doc runtime.MemProfileRate'' ).
63+ // allocated (see “ go doc runtime.MemProfileRate” ).
6464// Lowering the rate (for example, -memprofilerate 64000) produces
6565// a more fine-grained and therefore accurate profile, but it also incurs
6666// execution cost. For benchmark comparisons, never use timings
6767// obtained with a low -memprofilerate option.
6868//
69- // Example
69+ // # Example
7070//
7171// Assuming the base version of the compiler has been saved with
72- // `` toolstash save,'' this sequence compares the old and new compiler:
72+ // “ toolstash save,” this sequence compares the old and new compiler:
7373//
7474// compilebench -count 10 -compile $(toolstash -n compile) >old.txt
7575// compilebench -count 10 >new.txt
7676// benchstat old.txt new.txt
77- //
7877package main
7978
8079import (
8180 "bytes"
8281 "encoding/json"
8382 "flag"
8483 "fmt"
85- exec "golang.org/x/sys/execabs"
8684 "io/ioutil"
8785 "log"
8886 "os"
8987 "path/filepath"
9088 "regexp"
89+ "runtime"
9190 "strconv"
9291 "strings"
9392 "time"
93+
94+ exec "golang.org/x/sys/execabs"
9495)
9596
9697var (
97- goroot string
98- compiler string
99- linker string
100- runRE * regexp.Regexp
101- is6g bool
98+ goroot string
99+ compiler string
100+ assembler string
101+ linker string
102+ runRE * regexp.Regexp
103+ is6g bool
102104)
103105
104106var (
105107 flagGoCmd = flag .String ("go" , "go" , "path to \" go\" command" )
106108 flagAlloc = flag .Bool ("alloc" , false , "report allocations" )
107109 flagObj = flag .Bool ("obj" , false , "report object file stats" )
108110 flagCompiler = flag .String ("compile" , "" , "use `exe` as the cmd/compile binary" )
111+ flagAssembler = flag .String ("asm" , "" , "use `exe` as the cmd/asm binary" )
109112 flagCompilerFlags = flag .String ("compileflags" , "" , "additional `flags` to pass to compile" )
110113 flagLinker = flag .String ("link" , "" , "use `exe` as the cmd/link binary" )
111114 flagLinkerFlags = flag .String ("linkflags" , "" , "additional `flags` to pass to link" )
@@ -116,6 +119,7 @@ var (
116119 flagMemprofilerate = flag .Int64 ("memprofilerate" , - 1 , "set memory profile `rate`" )
117120 flagPackage = flag .String ("pkg" , "" , "if set, benchmark the package at path `pkg`" )
118121 flagShort = flag .Bool ("short" , false , "skip long-running benchmarks" )
122+ flagTrace = flag .Bool ("trace" , false , "debug tracing of builds" )
119123)
120124
121125type test struct {
@@ -178,6 +182,10 @@ func main() {
178182 is6g = true
179183 }
180184 }
185+ assembler = * flagAssembler
186+ if assembler == "" {
187+ _ , assembler = toolPath ("asm" )
188+ }
181189
182190 linker = * flagLinker
183191 if linker == "" && ! is6g { // TODO: Support 6l
@@ -238,8 +246,10 @@ func toolPath(names ...string) (found, path string) {
238246}
239247
240248type Pkg struct {
241- Dir string
242- GoFiles []string
249+ ImportPath string
250+ Dir string
251+ GoFiles []string
252+ SFiles []string
243253}
244254
245255func goList (dir string ) (* Pkg , error ) {
@@ -337,8 +347,30 @@ func (c compile) run(name string, count int) error {
337347 return err
338348 }
339349
340- args := []string {"-o" , "_compilebench_.o" }
350+ // If this package has assembly files, we'll need to pass a symabis
351+ // file to the compiler; call a helper to invoke the assembler
352+ // to do that.
353+ var symAbisFile string
354+ var asmIncFile string
355+ if len (pkg .SFiles ) != 0 {
356+ symAbisFile = filepath .Join (pkg .Dir , "symabis" )
357+ asmIncFile = filepath .Join (pkg .Dir , "go_asm.h" )
358+ content := "\n "
359+ if err := os .WriteFile (asmIncFile , []byte (content ), 0666 ); err != nil {
360+ return fmt .Errorf ("os.WriteFile(%s) failed: %v" , asmIncFile , err )
361+ }
362+ defer os .Remove (symAbisFile )
363+ defer os .Remove (asmIncFile )
364+ if err := genSymAbisFile (pkg , symAbisFile , pkg .Dir ); err != nil {
365+ return err
366+ }
367+ }
368+
369+ args := []string {"-o" , "_compilebench_.o" , "-p" , pkg .ImportPath }
341370 args = append (args , strings .Fields (* flagCompilerFlags )... )
371+ if symAbisFile != "" {
372+ args = append (args , "-symabis" , symAbisFile )
373+ }
342374 args = append (args , pkg .GoFiles ... )
343375 if err := runBuildCmd (name , count , pkg .Dir , compiler , args ); err != nil {
344376 return err
@@ -429,6 +461,10 @@ func runBuildCmd(name string, count int, dir, tool string, args []string) error
429461 preArgs = append (preArgs , "-cpuprofile" , "_compilebench_.cpuprof" )
430462 }
431463 }
464+ if * flagTrace {
465+ fmt .Fprintf (os .Stderr , "running: %s %+v\n " ,
466+ tool , append (preArgs , args ... ))
467+ }
432468 cmd := exec .Command (tool , append (preArgs , args ... )... )
433469 cmd .Dir = dir
434470 cmd .Stdout = os .Stderr
@@ -511,3 +547,34 @@ func runBuildCmd(name string, count int, dir, tool string, args []string) error
511547
512548 return nil
513549}
550+
551+ // genSymAbisFile runs the assembler on the target packge asm files
552+ // with "-gensymabis" to produce a symabis file that will feed into
553+ // the Go source compilation. This is fairly hacky in that if the
554+ // asm invocation convenion changes it will need to be updated
555+ // (hopefully that will not be needed too frequently).
556+ func genSymAbisFile (pkg * Pkg , symAbisFile , incdir string ) error {
557+ args := []string {"-gensymabis" , "-o" , symAbisFile ,
558+ "-p" , pkg .ImportPath ,
559+ "-I" , filepath .Join (goroot , "pkg" , "include" ),
560+ "-I" , incdir ,
561+ "-D" , "GOOS_" + runtime .GOOS ,
562+ "-D" , "GOARCH_" + runtime .GOARCH }
563+ if pkg .ImportPath == "reflect" {
564+ args = append (args , "-compiling-runtime" )
565+ }
566+ args = append (args , pkg .SFiles ... )
567+ if * flagTrace {
568+ fmt .Fprintf (os .Stderr , "running: %s %+v\n " ,
569+ assembler , args )
570+ }
571+ cmd := exec .Command (assembler , args ... )
572+ cmd .Dir = pkg .Dir
573+ cmd .Stdout = os .Stderr
574+ cmd .Stderr = os .Stderr
575+ err := cmd .Run ()
576+ if err != nil {
577+ return fmt .Errorf ("assembling to produce symabis file: %v" , err )
578+ }
579+ return nil
580+ }
0 commit comments