1
0
mirror of https://github.com/golang/go synced 2024-10-01 12:28:37 -06:00
go/ssa/stdlib_test.go
Alan Donovan e2921e188a go.tools/importer: make loading/parsing concurrent.
1. ParseFiles (in util.go) parses each file in its own goroutine.

2. (*Importer).LoadPackage asynchronously prefetches the
   import graph by scanning the imports of each loaded package
   and calling LoadPackage on each one.

   LoadPackage is now thread-safe and idempotent: it uses a
   condition variable per package; the first goroutine to
   request a package becomes responsible for loading it and
   broadcasts to the others (waiting) when it becomes ready.

ssadump runs 34% faster when loading the oracle.

Also, refactorings:
- delete SourceLoader mechanism; just expose go/build.Context directly.
- CreateSourcePackage now also returns an error directly,
  rather than via PackageInfo.Err, since every client wants that.

R=crawshaw
CC=golang-dev
https://golang.org/cl/13509045
2013-09-04 13:15:49 -04:00

125 lines
2.9 KiB
Go

// Copyright 2013 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 ssa_test
// This file runs the SSA builder in sanity-checking mode on all
// packages beneath $GOROOT and prints some summary information.
//
// Run test with GOMAXPROCS=8 and CGO_ENABLED=0. The latter cannot be
// set from the test because it's too late to stop go/build.init()
// from picking up the value from the parent's environment.
import (
"go/build"
"os"
"path/filepath"
"runtime"
"strings"
"testing"
"time"
"code.google.com/p/go.tools/importer"
"code.google.com/p/go.tools/ssa"
)
const debugMode = false
func allPackages() []string {
var pkgs []string
root := filepath.Join(runtime.GOROOT(), "src/pkg") + string(os.PathSeparator)
filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
// Prune the search if we encounter any of these names:
switch filepath.Base(path) {
case "testdata", ".hg":
return filepath.SkipDir
}
if info.IsDir() {
pkg := strings.TrimPrefix(path, root)
switch pkg {
case "builtin", "pkg", "code.google.com":
return filepath.SkipDir // skip these subtrees
case "":
return nil // ignore root of tree
}
pkgs = append(pkgs, pkg)
}
return nil
})
return pkgs
}
func TestStdlib(t *testing.T) {
ctxt := build.Default
ctxt.CgoEnabled = false // mutating a global!
impctx := importer.Config{Build: &ctxt}
// Load, parse and type-check the program.
t0 := time.Now()
var hasErrors bool
imp := importer.New(&impctx)
for _, importPath := range allPackages() {
if _, err := imp.LoadPackage(importPath); err != nil {
t.Errorf("LoadPackage(%s): %s", importPath, err)
hasErrors = true
}
}
t1 := time.Now()
runtime.GC()
var memstats runtime.MemStats
runtime.ReadMemStats(&memstats)
alloc := memstats.Alloc
// Create SSA packages.
prog := ssa.NewProgram(imp.Fset, ssa.SanityCheckFunctions)
for _, info := range imp.Packages {
if info.Err == nil {
prog.CreatePackage(info).SetDebugMode(debugMode)
}
}
t2 := time.Now()
// Build SSA IR... if it's safe.
if !hasErrors {
prog.BuildAll()
}
t3 := time.Now()
runtime.GC()
runtime.ReadMemStats(&memstats)
numPkgs := len(prog.PackagesByPath)
if want := 140; numPkgs < want {
t.Errorf("Loaded only %d packages, want at least %d", numPkgs, want)
}
// Dump some statistics.
allFuncs := ssa.AllFunctions(prog)
var numInstrs int
for fn := range allFuncs {
for _, b := range fn.Blocks {
numInstrs += len(b.Instrs)
}
}
t.Log("GOMAXPROCS: ", runtime.GOMAXPROCS(0))
t.Log("Load/parse/typecheck: ", t1.Sub(t0))
t.Log("SSA create: ", t2.Sub(t1))
if !hasErrors {
t.Log("SSA build: ", t3.Sub(t2))
}
// SSA stats:
t.Log("#Packages: ", numPkgs)
t.Log("#Functions: ", len(allFuncs))
t.Log("#Instructions: ", numInstrs)
t.Log("#MB: ", (memstats.Alloc-alloc)/1000000)
}