func main() { st := new(runtime.MemStats) packages = append(packages, packages...) packages = append(packages, packages...) n := flag.Int("n", 4, "iterations") p := flag.Int("p", len(packages), "# of packages to keep in memory") flag.BoolVar(&st.DebugGC, "d", st.DebugGC, "print GC debugging info (pause times)") flag.Parse() var lastParsed []map[string]*ast.Package var t0 time.Time var numGC uint32 var pauseTotalNs uint64 pkgroot := runtime.GOROOT() + "/src/" for pass := 0; pass < 2; pass++ { // Once the heap is grown to full size, reset counters. // This hides the start-up pauses, which are much smaller // than the normal pauses and would otherwise make // the average look much better than it actually is. runtime.ReadMemStats(st) numGC = st.NumGC pauseTotalNs = st.PauseTotalNs t0 = time.Now() for i := 0; i < *n; i++ { parsed := make([]map[string]*ast.Package, *p) for j := range parsed { parsed[j] = parseDir(pkgroot + packages[j%len(packages)]) } if i+1 == *n && *serve != "" { lastParsed = parsed } } runtime.GC() runtime.GC() } t1 := time.Now() runtime.ReadMemStats(st) st.NumGC -= numGC st.PauseTotalNs -= pauseTotalNs fmt.Printf("Alloc=%d/%d Heap=%d Mallocs=%d PauseTime=%.3f/%d = %.3f\n", st.Alloc, st.TotalAlloc, st.Sys, st.Mallocs, float64(st.PauseTotalNs)/1e9, st.NumGC, float64(st.PauseTotalNs)/1e9/float64(st.NumGC)) /* fmt.Printf("%10s %10s %10s\n", "size", "#alloc", "#free") for _, s := range st.BySize { fmt.Printf("%10d %10d %10d\n", s.Size, s.Mallocs, s.Frees) } */ // Standard gotest benchmark output, collected by build dashboard. gcstats("BenchmarkParser", *n, t1.Sub(t0)) if *serve != "" { log.Fatal(http.ListenAndServe(*serve, nil)) println(lastParsed) } }
// MemThresholds is a convenience function to create a thresholds memory stats from // offsets to apply to the current memory stats. Zero values in the offset stats // are left to 0 in the resulting thresholds memory stats value. // // The return value may be used as thresholds argument to the MemStats function. func MemThresholds(offset *runtime.MemStats) *runtime.MemStats { var mem, thr runtime.MemStats runtime.ReadMemStats(&mem) if offset.Alloc > 0 { thr.Alloc = mem.Alloc + offset.Alloc } if offset.BuckHashSys > 0 { thr.BuckHashSys = mem.BuckHashSys + offset.BuckHashSys } if offset.Frees > 0 { thr.Frees = mem.Frees + offset.Frees } if offset.GCSys > 0 { thr.GCSys = mem.GCSys + offset.GCSys } if offset.HeapAlloc > 0 { thr.HeapAlloc = mem.HeapAlloc + offset.HeapAlloc } if offset.HeapIdle > 0 { thr.HeapIdle = mem.HeapIdle + offset.HeapIdle } if offset.HeapInuse > 0 { thr.HeapInuse = mem.HeapInuse + offset.HeapInuse } if offset.HeapObjects > 0 { thr.HeapObjects = mem.HeapObjects + offset.HeapObjects } if offset.HeapReleased > 0 { thr.HeapReleased = mem.HeapReleased + offset.HeapReleased } if offset.HeapSys > 0 { thr.HeapSys = mem.HeapSys + offset.HeapSys } if offset.LastGC > 0 { thr.LastGC = mem.LastGC + offset.LastGC } if offset.Lookups > 0 { thr.Lookups = mem.Lookups + offset.Lookups } if offset.MCacheInuse > 0 { thr.MCacheInuse = mem.MCacheInuse + offset.MCacheInuse } if offset.MCacheSys > 0 { thr.MCacheSys = mem.MCacheSys + offset.MCacheSys } if offset.MSpanInuse > 0 { thr.MSpanInuse = mem.MSpanInuse + offset.MSpanInuse } if offset.MSpanSys > 0 { thr.MSpanSys = mem.MSpanSys + offset.MSpanSys } if offset.Mallocs > 0 { thr.Mallocs = mem.Mallocs + offset.Mallocs } if offset.NextGC > 0 { thr.NextGC = mem.NextGC + offset.NextGC } if offset.NumGC > 0 { thr.NumGC = mem.NumGC + offset.NumGC } if offset.OtherSys > 0 { thr.OtherSys = mem.OtherSys + offset.OtherSys } if offset.PauseTotalNs > 0 { thr.PauseTotalNs = mem.PauseTotalNs + offset.PauseTotalNs } if offset.StackInuse > 0 { thr.StackInuse = mem.StackInuse + offset.StackInuse } if offset.StackSys > 0 { thr.StackSys = mem.StackSys + offset.StackSys } if offset.Sys > 0 { thr.Sys = mem.Sys + offset.Sys } if offset.TotalAlloc > 0 { thr.TotalAlloc = mem.TotalAlloc + offset.TotalAlloc } return &thr }
// (10) memstats func readMemStats(r io.ByteReader) *runtime.MemStats { var memStats runtime.MemStats memStats.Alloc = readUvarint(r) // bytes allocated and still in use memStats.TotalAlloc = readUvarint(r) // bytes allocated (even if freed) memStats.Sys = readUvarint(r) // bytes obtained from system (sum of XxxSys below) memStats.Lookups = readUvarint(r) // number of pointer lookups memStats.Mallocs = readUvarint(r) // number of mallocs memStats.Frees = readUvarint(r) // number of frees memStats.HeapAlloc = readUvarint(r) // bytes allocated and still in use memStats.HeapSys = readUvarint(r) // bytes obtained from system memStats.HeapIdle = readUvarint(r) // bytes in idle spans memStats.HeapInuse = readUvarint(r) // bytes in non-idle span memStats.HeapReleased = readUvarint(r) // bytes released to the OS memStats.HeapObjects = readUvarint(r) // total number of allocated objects memStats.StackInuse = readUvarint(r) // bootstrap stacks memStats.StackSys = readUvarint(r) memStats.MSpanInuse = readUvarint(r) // mspan structures memStats.MSpanSys = readUvarint(r) memStats.MCacheInuse = readUvarint(r) // mcache structures memStats.MCacheSys = readUvarint(r) memStats.BuckHashSys = readUvarint(r) // profiling bucket hash table memStats.GCSys = readUvarint(r) // GC metadata memStats.OtherSys = readUvarint(r) // other system allocations memStats.NextGC = readUvarint(r) // next run in HeapAlloc time (bytes) memStats.LastGC = readUvarint(r) // last run in absolute time (ns) memStats.PauseTotalNs = readUvarint(r) for i := 0; i < 256; i++ { memStats.PauseNs[i] = readUvarint(r) } memStats.NumGC = uint32(readUvarint(r)) return &memStats }