1 // Copyright 2010 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.
5 // Garbage collection benchmark: parse Go packages repeatedly.
21 func isGoFile(dir *os.FileInfo) bool {
22 return dir.IsRegular() &&
23 !strings.HasPrefix(dir.Name, ".") && // ignore .files
24 path.Ext(dir.Name) == ".go"
27 func isPkgFile(dir *os.FileInfo) bool {
28 return isGoFile(dir) &&
29 !strings.HasSuffix(dir.Name, "_test.go") // ignore test files
32 func pkgName(filename string) string {
33 file, err := parser.ParseFile(filename, nil, parser.PackageClauseOnly)
34 if err != nil || file == nil {
40 func parseDir(dirpath string) map[string]*ast.Package {
41 // the package name is the directory name within its parent
42 // (use dirname instead of path because dirname is clean; i.e. has no trailing '/')
43 _, pkgname := path.Split(dirpath)
45 // filter function to select the desired .go files
46 filter := func(d *os.FileInfo) bool {
48 // Some directories contain main packages: Only accept
49 // files that belong to the expected package so that
50 // parser.ParsePackage doesn't return "multiple packages
52 // Additionally, accept the special package name
53 // fakePkgName if we are looking at cmd documentation.
54 name := pkgName(dirpath + "/" + d.Name)
55 return name == pkgname
61 pkgs, err := parser.ParseDir(dirpath, filter, parser.ParseComments)
63 println("parse", dirpath, err.String())
70 st := &runtime.MemStats
71 n := flag.Int("n", 4, "iterations")
72 p := flag.Int("p", len(packages), "# of packages to keep in memory")
73 flag.BoolVar(&st.DebugGC, "d", st.DebugGC, "print GC debugging info (pause times)")
77 pkgroot := runtime.GOROOT() + "/src/pkg/"
78 for pass := 0; pass < 2; pass++ {
79 // Once the heap is grown to full size, reset counters.
80 // This hides the start-up pauses, which are much smaller
81 // than the normal pauses and would otherwise make
82 // the average look much better than it actually is.
85 t0 = time.Nanoseconds()
87 for i := 0; i < *n; i++ {
88 parsed := make([]map[string]*ast.Package, *p)
89 for j := range parsed {
90 parsed[j] = parseDir(pkgroot + packages[j%len(packages)])
95 t1 := time.Nanoseconds()
97 fmt.Printf("Alloc=%d/%d Heap=%d Mallocs=%d PauseTime=%.3f/%d = %.3f\n",
98 st.Alloc, st.TotalAlloc,
100 st.Mallocs, float64(st.PauseNs)/1e9,
101 st.NumGC, float64(st.PauseNs)/1e9/float64(st.NumGC))
103 fmt.Printf("%10s %10s %10s\n", "size", "#alloc", "#free")
104 for _, s := range st.BySize {
105 fmt.Printf("%10d %10d %10d\n", s.Size, s.Mallocs, s.Frees)
108 // Standard gotest benchmark output, collected by build dashboard.
109 fmt.Printf("garbage.BenchmarkParser %d %d ns/op\n", *n, (t1-t0)/int64(*n))
110 fmt.Printf("garbage.BenchmarkParserPause %d %d ns/op\n", st.NumGC, int64(st.PauseNs)/int64(st.NumGC))
114 var packages = []string{