github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/tools/go/ssa/stdlib_test.go (about)

     1  // Copyright 2013 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  // Incomplete source tree on Android.
     6  
     7  // +build !android
     8  
     9  package ssa_test
    10  
    11  // This file runs the SSA builder in sanity-checking mode on all
    12  // packages beneath $GOROOT and prints some summary information.
    13  //
    14  // Run with "go test -cpu=8 to" set GOMAXPROCS.
    15  
    16  import (
    17  	"go/ast"
    18  	"go/build"
    19  	"go/token"
    20  	"runtime"
    21  	"testing"
    22  	"time"
    23  
    24  	"golang.org/x/tools/go/buildutil"
    25  	"golang.org/x/tools/go/loader"
    26  	"golang.org/x/tools/go/ssa"
    27  	"golang.org/x/tools/go/ssa/ssautil"
    28  )
    29  
    30  // Skip the set of packages that transitively depend on
    31  // cmd/internal/objfile, which uses vendoring,
    32  // which go/loader does not yet support.
    33  // TODO(adonovan): add support for vendoring and delete this.
    34  var skip = map[string]bool{
    35  	"cmd/addr2line":        true,
    36  	"cmd/internal/objfile": true,
    37  	"cmd/nm":               true,
    38  	"cmd/objdump":          true,
    39  	"cmd/pprof":            true,
    40  }
    41  
    42  func bytesAllocated() uint64 {
    43  	runtime.GC()
    44  	var stats runtime.MemStats
    45  	runtime.ReadMemStats(&stats)
    46  	return stats.Alloc
    47  }
    48  
    49  func TestStdlib(t *testing.T) {
    50  	// Load, parse and type-check the program.
    51  	t0 := time.Now()
    52  	alloc0 := bytesAllocated()
    53  
    54  	// Load, parse and type-check the program.
    55  	ctxt := build.Default // copy
    56  	ctxt.GOPATH = ""      // disable GOPATH
    57  	conf := loader.Config{Build: &ctxt}
    58  	for _, path := range buildutil.AllPackages(conf.Build) {
    59  		if skip[path] {
    60  			continue
    61  		}
    62  		conf.ImportWithTests(path)
    63  	}
    64  
    65  	iprog, err := conf.Load()
    66  	if err != nil {
    67  		t.Fatalf("Load failed: %v", err)
    68  	}
    69  
    70  	t1 := time.Now()
    71  	alloc1 := bytesAllocated()
    72  
    73  	// Create SSA packages.
    74  	var mode ssa.BuilderMode
    75  	// Comment out these lines during benchmarking.  Approx SSA build costs are noted.
    76  	mode |= ssa.SanityCheckFunctions // + 2% space, + 4% time
    77  	mode |= ssa.GlobalDebug          // +30% space, +18% time
    78  	prog := ssautil.CreateProgram(iprog, mode)
    79  
    80  	t2 := time.Now()
    81  
    82  	// Build SSA.
    83  	prog.Build()
    84  
    85  	t3 := time.Now()
    86  	alloc3 := bytesAllocated()
    87  
    88  	numPkgs := len(prog.AllPackages())
    89  	if want := 140; numPkgs < want {
    90  		t.Errorf("Loaded only %d packages, want at least %d", numPkgs, want)
    91  	}
    92  
    93  	// Keep iprog reachable until after we've measured memory usage.
    94  	if len(iprog.AllPackages) == 0 {
    95  		print() // unreachable
    96  	}
    97  
    98  	allFuncs := ssautil.AllFunctions(prog)
    99  
   100  	// Check that all non-synthetic functions have distinct names.
   101  	// Synthetic wrappers for exported methods should be distinct too,
   102  	// except for unexported ones (explained at (*Function).RelString).
   103  	byName := make(map[string]*ssa.Function)
   104  	for fn := range allFuncs {
   105  		if fn.Synthetic == "" || ast.IsExported(fn.Name()) {
   106  			str := fn.String()
   107  			prev := byName[str]
   108  			byName[str] = fn
   109  			if prev != nil {
   110  				t.Errorf("%s: duplicate function named %s",
   111  					prog.Fset.Position(fn.Pos()), str)
   112  				t.Errorf("%s:   (previously defined here)",
   113  					prog.Fset.Position(prev.Pos()))
   114  			}
   115  		}
   116  	}
   117  
   118  	// Dump some statistics.
   119  	var numInstrs int
   120  	for fn := range allFuncs {
   121  		for _, b := range fn.Blocks {
   122  			numInstrs += len(b.Instrs)
   123  		}
   124  	}
   125  
   126  	// determine line count
   127  	var lineCount int
   128  	prog.Fset.Iterate(func(f *token.File) bool {
   129  		lineCount += f.LineCount()
   130  		return true
   131  	})
   132  
   133  	// NB: when benchmarking, don't forget to clear the debug +
   134  	// sanity builder flags for better performance.
   135  
   136  	t.Log("GOMAXPROCS:           ", runtime.GOMAXPROCS(0))
   137  	t.Log("#Source lines:        ", lineCount)
   138  	t.Log("Load/parse/typecheck: ", t1.Sub(t0))
   139  	t.Log("SSA create:           ", t2.Sub(t1))
   140  	t.Log("SSA build:            ", t3.Sub(t2))
   141  
   142  	// SSA stats:
   143  	t.Log("#Packages:            ", numPkgs)
   144  	t.Log("#Functions:           ", len(allFuncs))
   145  	t.Log("#Instructions:        ", numInstrs)
   146  	t.Log("#MB AST+types:        ", int64(alloc1-alloc0)/1e6)
   147  	t.Log("#MB SSA:              ", int64(alloc3-alloc1)/1e6)
   148  }