blob: 6f59e1e7a852b0fdbd87f2b24d472fe0469ef2de [file] [log] [blame]
// +build ignore,OMIT
package main
import (
"fmt"
"go/ast"
"go/parser"
"go/token"
"io/ioutil"
"path/filepath"
"runtime"
"sort"
"strings"
"time"
)
func walk(dir string, f func(string) bool) bool {
fis, err := ioutil.ReadDir(dir)
if err != nil {
panic(err)
}
// parse all *.go files in directory;
// traverse subdirectories, but don't walk into testdata
for _, fi := range fis {
path := filepath.Join(dir, fi.Name())
if fi.IsDir() {
if fi.Name() != "testdata" {
if !walk(path, f) {
return false
}
}
} else if strings.HasSuffix(fi.Name(), ".go") && !strings.HasPrefix(fi.Name(), ".") {
if !f(path) {
return false
}
}
}
return true
}
func walkStdLib(f func(filename string) bool) {
walk(filepath.Join(runtime.GOROOT(), "src"), f)
}
type histogram map[string]int
func (h histogram) add(filename string) {
f, err := parser.ParseFile(token.NewFileSet(), filename, nil, 0)
if err != nil {
panic(err)
}
ast.Inspect(f, func(n ast.Node) bool {
if n, ok := n.(ast.Stmt); ok {
h[fmt.Sprintf("%T", n)]++
}
return true
})
}
// merge START OMIT
func (h histogram) merge(h1 histogram) {
for key, count := range h1 {
h[key] = h[key] + count
}
}
// merge END OMIT
type entry struct {
key string
count int
}
func (h histogram) print() {
var list []entry
var total int
for key, count := range h {
list = append(list, entry{key, count})
total += count
}
sort.Sort(byCount(list))
percent := 100 / float64(total)
for i, e := range list {
fmt.Printf("%4d. %5.2f%% %5d %s\n", i, float64(e.count)*percent, e.count, e.key)
}
}
type byCount []entry
func (s byCount) Len() int { return len(s) }
func (s byCount) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s byCount) Less(i, j int) bool {
x, y := s[i], s[j]
if x.count != y.count {
return x.count > y.count // want larger count first
}
return x.key < y.key
}
func init() {
n := runtime.NumCPU()
//fmt.Println(n, "cores")
runtime.GOMAXPROCS(n)
}
// main START OMIT
func main() {
start := time.Now()
ch := make(chan histogram)
count := 0 // goroutine count
walkStdLib(func(filename string) bool {
count++
// mapper START OMIT
go func() {
h := make(histogram)
h.add(filename)
ch <- h
}()
// mapper END OMIT
return true
})
// reducer START OMIT
h := make(histogram)
for count > 0 {
h.merge(<-ch)
count--
}
// reducer END OMIT
h.print()
fmt.Println(time.Since(start))
}
// main END OMIT