modernc.org/gc@v1.0.1-0.20240304020402-f0dba7c97c2b/testdata/errchk/test/bench/garbage/parser.go (about)

     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.
     4  
     5  // Garbage collection benchmark: parse Go packages repeatedly.
     6  
     7  package main
     8  
     9  import (
    10  	"flag"
    11  	"fmt"
    12  	"go/ast"
    13  	"go/parser"
    14  	"go/token"
    15  	"log"
    16  	"net/http"
    17  	_ "net/http/pprof"
    18  	"os"
    19  	"path"
    20  	"runtime"
    21  	"strings"
    22  	"time"
    23  )
    24  
    25  var serve = flag.String("serve", "", "serve http on this address at end")
    26  
    27  func isGoFile(dir os.FileInfo) bool {
    28  	return !dir.IsDir() &&
    29  		!strings.HasPrefix(dir.Name(), ".") && // ignore .files
    30  		path.Ext(dir.Name()) == ".go"
    31  }
    32  
    33  func isPkgFile(dir os.FileInfo) bool {
    34  	return isGoFile(dir) &&
    35  		!strings.HasSuffix(dir.Name(), "_test.go") // ignore test files
    36  }
    37  
    38  func pkgName(filename string) string {
    39  	file, err := parser.ParseFile(token.NewFileSet(), filename, nil, parser.PackageClauseOnly)
    40  	if err != nil || file == nil {
    41  		return ""
    42  	}
    43  	return file.Name.Name
    44  }
    45  
    46  func parseDir(dirpath string) map[string]*ast.Package {
    47  	// the package name is the directory name within its parent
    48  	// (use dirname instead of path because dirname is clean; i.e. has no trailing '/')
    49  	_, pkgname := path.Split(dirpath)
    50  
    51  	// filter function to select the desired .go files
    52  	filter := func(d os.FileInfo) bool {
    53  		if isPkgFile(d) {
    54  			// Some directories contain main packages: Only accept
    55  			// files that belong to the expected package so that
    56  			// parser.ParsePackage doesn't return "multiple packages
    57  			// found" errors.
    58  			// Additionally, accept the special package name
    59  			// fakePkgName if we are looking at cmd documentation.
    60  			name := pkgName(dirpath + "/" + d.Name())
    61  			return name == pkgname
    62  		}
    63  		return false
    64  	}
    65  
    66  	// get package AST
    67  	pkgs, err := parser.ParseDir(token.NewFileSet(), dirpath, filter, parser.ParseComments)
    68  	if err != nil {
    69  		println("parse", dirpath, err.Error())
    70  		panic("fail")
    71  	}
    72  	return pkgs
    73  }
    74  
    75  func main() {
    76  	st := new(runtime.MemStats)
    77  	packages = append(packages, packages...)
    78  	packages = append(packages, packages...)
    79  	n := flag.Int("n", 4, "iterations")
    80  	p := flag.Int("p", len(packages), "# of packages to keep in memory")
    81  	flag.BoolVar(&st.DebugGC, "d", st.DebugGC, "print GC debugging info (pause times)")
    82  	flag.Parse()
    83  
    84  	var lastParsed []map[string]*ast.Package
    85  	var t0 time.Time
    86  	var numGC uint32
    87  	var pauseTotalNs uint64
    88  	pkgroot := runtime.GOROOT() + "/src/"
    89  	for pass := 0; pass < 2; pass++ {
    90  		// Once the heap is grown to full size, reset counters.
    91  		// This hides the start-up pauses, which are much smaller
    92  		// than the normal pauses and would otherwise make
    93  		// the average look much better than it actually is.
    94  		runtime.ReadMemStats(st)
    95  		numGC = st.NumGC
    96  		pauseTotalNs = st.PauseTotalNs
    97  		t0 = time.Now()
    98  
    99  		for i := 0; i < *n; i++ {
   100  			parsed := make([]map[string]*ast.Package, *p)
   101  			for j := range parsed {
   102  				parsed[j] = parseDir(pkgroot + packages[j%len(packages)])
   103  			}
   104  			if i+1 == *n && *serve != "" {
   105  				lastParsed = parsed
   106  			}
   107  		}
   108  		runtime.GC()
   109  		runtime.GC()
   110  	}
   111  	t1 := time.Now()
   112  
   113  	runtime.ReadMemStats(st)
   114  	st.NumGC -= numGC
   115  	st.PauseTotalNs -= pauseTotalNs
   116  	fmt.Printf("Alloc=%d/%d Heap=%d Mallocs=%d PauseTime=%.3f/%d = %.3f\n",
   117  		st.Alloc, st.TotalAlloc,
   118  		st.Sys,
   119  		st.Mallocs, float64(st.PauseTotalNs)/1e9,
   120  		st.NumGC, float64(st.PauseTotalNs)/1e9/float64(st.NumGC))
   121  
   122  	/*
   123  		fmt.Printf("%10s %10s %10s\n", "size", "#alloc", "#free")
   124  		for _, s := range st.BySize {
   125  			fmt.Printf("%10d %10d %10d\n", s.Size, s.Mallocs, s.Frees)
   126  		}
   127  	*/
   128  	// Standard gotest benchmark output, collected by build dashboard.
   129  	gcstats("BenchmarkParser", *n, t1.Sub(t0))
   130  
   131  	if *serve != "" {
   132  		log.Fatal(http.ListenAndServe(*serve, nil))
   133  		println(lastParsed)
   134  	}
   135  }
   136  
   137  // find . -type d -not -path "./exp" -not -path "./exp/*" -printf "\t\"%p\",\n" | sort | sed "s/\.\///" | grep -v testdata
   138  var packages = []string{
   139  	"archive",
   140  	"archive/tar",
   141  	"archive/zip",
   142  	"bufio",
   143  	"builtin",
   144  	"bytes",
   145  	"compress",
   146  	"compress/bzip2",
   147  	"compress/flate",
   148  	"compress/gzip",
   149  	"compress/lzw",
   150  	"compress/zlib",
   151  	"container",
   152  	"container/heap",
   153  	"container/list",
   154  	"container/ring",
   155  	"crypto",
   156  	"crypto/aes",
   157  	"crypto/cipher",
   158  	"crypto/des",
   159  	"crypto/dsa",
   160  	"crypto/ecdsa",
   161  	"crypto/elliptic",
   162  	"crypto/hmac",
   163  	"crypto/md5",
   164  	"crypto/rand",
   165  	"crypto/rc4",
   166  	"crypto/rsa",
   167  	"crypto/sha1",
   168  	"crypto/sha256",
   169  	"crypto/sha512",
   170  	"crypto/subtle",
   171  	"crypto/tls",
   172  	"crypto/x509",
   173  	"crypto/x509/pkix",
   174  	"database",
   175  	"database/sql",
   176  	"database/sql/driver",
   177  	"debug",
   178  	"debug/dwarf",
   179  	"debug/elf",
   180  	"debug/gosym",
   181  	"debug/macho",
   182  	"debug/pe",
   183  	"encoding",
   184  	"encoding/ascii85",
   185  	"encoding/asn1",
   186  	"encoding/base32",
   187  	"encoding/base64",
   188  	"encoding/binary",
   189  	"encoding/csv",
   190  	"encoding/gob",
   191  	"encoding/hex",
   192  	"encoding/json",
   193  	"encoding/pem",
   194  	"encoding/xml",
   195  	"errors",
   196  	"expvar",
   197  	"flag",
   198  	"fmt",
   199  	"go",
   200  	"go/ast",
   201  	"go/build",
   202  	"go/doc",
   203  	"go/format",
   204  	"go/parser",
   205  	"go/printer",
   206  	"go/scanner",
   207  	"go/token",
   208  	"hash",
   209  	"hash/adler32",
   210  	"hash/crc32",
   211  	"hash/crc64",
   212  	"hash/fnv",
   213  	"html",
   214  	"html/template",
   215  	"image",
   216  	"image/color",
   217  	"image/draw",
   218  	"image/gif",
   219  	"image/jpeg",
   220  	"image/png",
   221  	"index",
   222  	"index/suffixarray",
   223  	"io",
   224  	"io/ioutil",
   225  	"log",
   226  	"log/syslog",
   227  	"math",
   228  	"math/big",
   229  	"math/cmplx",
   230  	"math/rand",
   231  	"mime",
   232  	"mime/multipart",
   233  	"net",
   234  	"net/http",
   235  	"net/http/cgi",
   236  	"net/http/cookiejar",
   237  	"net/http/fcgi",
   238  	"net/http/httptest",
   239  	"net/http/httputil",
   240  	"net/http/pprof",
   241  	"net/mail",
   242  	"net/rpc",
   243  	"net/rpc/jsonrpc",
   244  	"net/smtp",
   245  	"net/textproto",
   246  	"net/url",
   247  	"os",
   248  	"os/exec",
   249  	"os/signal",
   250  	"os/user",
   251  	"path",
   252  	"path/filepath",
   253  	"reflect",
   254  	"regexp",
   255  	"regexp/syntax",
   256  	"runtime",
   257  	"runtime/cgo",
   258  	"runtime/debug",
   259  	"runtime/pprof",
   260  	"runtime/race",
   261  	"sort",
   262  	"strconv",
   263  	"strings",
   264  	"sync",
   265  	"sync/atomic",
   266  	"syscall",
   267  	"testing",
   268  	"testing/iotest",
   269  	"testing/quick",
   270  	"text",
   271  	"text/scanner",
   272  	"text/tabwriter",
   273  	"text/template",
   274  	"text/template/parse",
   275  	"time",
   276  	"unicode",
   277  	"unicode/utf16",
   278  	"unicode/utf8",
   279  	"unsafe",
   280  }