github.com/amarpal/go-tools@v0.0.0-20240422043104-40142f59f616/go/ir/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 //lint:file-ignore SA1019 go/ssa's test suite is built around the deprecated go/loader. We'll leave fixing that to upstream. 6 7 // Incomplete source tree on Android. 8 9 //go:build !android 10 // +build !android 11 12 package ir_test 13 14 // This file runs the IR builder in sanity-checking mode on all 15 // packages beneath $GOROOT and prints some summary information. 16 // 17 // Run with "go test -cpu=8 to" set GOMAXPROCS. 18 19 import ( 20 "go/ast" 21 "go/token" 22 "runtime" 23 "testing" 24 "time" 25 26 "github.com/amarpal/go-tools/go/ir" 27 "github.com/amarpal/go-tools/go/ir/irutil" 28 29 "golang.org/x/tools/go/packages" 30 ) 31 32 func bytesAllocated() uint64 { 33 runtime.GC() 34 var stats runtime.MemStats 35 runtime.ReadMemStats(&stats) 36 return stats.TotalAlloc 37 } 38 39 func TestStdlib(t *testing.T) { 40 if testing.Short() { 41 t.Skip("skipping in short mode; too slow (golang.org/issue/14113)") 42 } 43 44 var ( 45 numFuncs int 46 numInstrs int 47 48 dLoad time.Duration 49 dCreate time.Duration 50 dBuild time.Duration 51 52 allocLoad uint64 53 allocBuild uint64 54 ) 55 56 // Load, parse and type-check the program. 57 t0 := time.Now() 58 alloc0 := bytesAllocated() 59 60 cfg := &packages.Config{ 61 Mode: packages.NeedName | packages.NeedFiles | packages.NeedCompiledGoFiles | packages.NeedImports | packages.NeedDeps | packages.NeedTypes | packages.NeedSyntax | packages.NeedTypesInfo | packages.NeedTypesSizes, 62 } 63 pkgs, err := packages.Load(cfg, "std") 64 if err != nil { 65 t.Fatalf("Load failed: %v", err) 66 } 67 allocLoad = bytesAllocated() - alloc0 68 dLoad = time.Since(t0) 69 70 alloc0 = bytesAllocated() 71 for _, pkg := range pkgs { 72 if len(pkg.Errors) != 0 { 73 t.Fatalf("Load failed: %v", pkg.Errors) 74 } 75 76 var mode ir.BuilderMode 77 // Comment out these lines during benchmarking. Approx IR build costs are noted. 78 mode |= ir.SanityCheckFunctions // + 2% space, + 4% time 79 mode |= ir.GlobalDebug // +30% space, +18% time 80 prog := ir.NewProgram(pkg.Fset, mode) 81 82 t0 := time.Now() 83 var irpkg *ir.Package 84 for _, pkg2 := range pkgs { 85 r := prog.CreatePackage(pkg2.Types, pkg2.Syntax, pkg2.TypesInfo, true) 86 if pkg2 == pkg { 87 irpkg = r 88 } 89 } 90 dCreate += time.Since(t0) 91 92 t0 = time.Now() 93 irpkg.Build() 94 dBuild += time.Since(t0) 95 96 allFuncs := irutil.AllFunctions(prog) 97 numFuncs += len(allFuncs) 98 99 // Check that all non-synthetic functions have distinct names. 100 // Synthetic wrappers for exported methods should be distinct too, 101 // except for unexported ones (explained at (*Function).RelString). 102 byName := make(map[string]*ir.Function) 103 for fn := range allFuncs { 104 if fn.Synthetic == 0 || (ast.IsExported(fn.Name()) && fn.Synthetic != ir.SyntheticGeneric) { 105 str := fn.String() 106 prev := byName[str] 107 byName[str] = fn 108 if prev != nil { 109 t.Errorf("%s: duplicate function named %s", 110 prog.Fset.Position(fn.Pos()), str) 111 t.Errorf("%s: (previously defined here)", 112 prog.Fset.Position(prev.Pos())) 113 } 114 } 115 } 116 117 // Dump some statistics. 118 var numInstrs int 119 for fn := range allFuncs { 120 for _, b := range fn.Blocks { 121 numInstrs += len(b.Instrs) 122 } 123 } 124 } 125 allocBuild = bytesAllocated() - alloc0 126 127 // determine line count 128 var lineCount int 129 pkgs[0].Fset.Iterate(func(f *token.File) bool { 130 lineCount += f.LineCount() 131 return true 132 }) 133 134 // NB: when benchmarking, don't forget to clear the debug + 135 // sanity builder flags for better performance. 136 137 t.Log("GOMAXPROCS: ", runtime.GOMAXPROCS(0)) 138 t.Log("#Source lines: ", lineCount) 139 t.Log("Load/parse/typecheck: ", dLoad) 140 t.Log("IR create: ", dCreate) 141 t.Log("IR build: ", dBuild) 142 143 // IR stats: 144 t.Log("#Packages: ", len(pkgs)) 145 t.Log("#Functions: ", numFuncs) 146 t.Log("#Instructions: ", numInstrs) 147 t.Log("#MB AST+types: ", allocLoad/1e6) 148 t.Log("#MB IR: ", allocBuild/1e6) 149 }