func BenchmarkHeapProfile(b *testing.B) { f, err := os.Open("testdata/__prof") if err != nil { b.Fatal(err) } defer f.Close() p, err := parser.NewHeapProfParser(f) if err != nil { b.Fatal(err) } bsize := int64(0) for i := 0; i < b.N; i++ { rec, err := p.ReadRecord() if err == io.EOF { // rewind. bsize += tell(f) f.Seek(0, 0) p, _ = parser.NewHeapProfParser(f) continue } _ = rec } bsize += tell(f) b.SetBytes(bsize / int64(b.N)) }
func TestHeapProfile(t *testing.T) { f, err := os.Open("testdata/heap.prof") if err != nil { t.Fatal(err) } defer f.Close() p, err := parser.NewHeapProfParser(f) if err != nil { t.Fatal(err) } syms := readSymbols("testdata/heap.prof.symbols") printed := 0 for { rec, err := p.ReadRecord() if err == io.EOF { break } s := stringify(rec.Trace, syms) if printed < 10 { printed++ t.Logf("%d:%d [%d:%d] @ %v", rec.LiveObj, rec.LiveBytes, rec.AllocObj, rec.AllocBytes, s) } } }
func TestHeapProfileReport(t *testing.T) { f, err := os.Open("testdata/heap.prof") if err != nil { t.Fatal(err) } defer f.Close() p, err := parser.NewHeapProfParser(f) if err != nil { t.Fatal(err) } syms := readSymbols("testdata/heap.prof.symbols") resolve := func(u uint64) string { s, _ := lookup(u, syms); return s } reporter := &Reporter{Resolver: resolve} for { rec, err := p.ReadRecord() if err == io.EOF { break } p.AdjustRecord(&rec, resolve) reporter.Add(rec.Trace, rec.LiveObj, rec.LiveBytes, rec.AllocObj, rec.AllocBytes) } entries := reporter.ReportByFunc(ColAllocBytes) buf := new(bytes.Buffer) w := tabwriter.NewWriter(buf, 0, 8, 2, ' ', 0) fmt.Fprintf(w, "\nalloc space\tallocs\tin use space\tin use count\tFunction\n") const MB = 1 << 20 for _, e := range entries { fmt.Fprintf(w, "%.5g\t%d\t%.3g\t%d\t%s\n", e.Self[ColAllocBytes]/MB, int64(e.Self[ColAllocObj]), e.Self[ColLiveBytes]/MB, int64(e.Self[ColLiveObj]), e.Name) } w.Flush() t.Log(buf.String()) }
func LoadProfile(r *report.Reporter, f io.ReadCloser) { defer f.Close() buf := bufio.NewReader(f) magic, _ := buf.Peek(4) switch string(magic) { case "heap": // Heap profile. p, err := parser.NewHeapProfParser(buf) if err != nil { log.Fatal(err) } for { rec, err := p.ReadRecord() if err == io.EOF { break } p.AdjustRecord(&rec, func(uint64) string { return "" }) r.Add(rec.Trace, rec.LiveObj, rec.LiveBytes, rec.AllocObj, rec.AllocBytes) } default: // CPU Profile. p, err := parser.NewCpuProfParser(buf) if err != nil { log.Fatal(err) } for { trace, count, err := p.ReadTrace() if trace == nil && err == io.EOF { break } r.Add(trace, int64(count)) } } }
Expect(profiler.Profile).To(Panic()) }) }) Describe("memory profiling", func() { It("profiles memory usage", func() { profiler := profiler.New("", memProfilePath, 1*time.Millisecond, logger) profiler.Profile() time.Sleep(2 * time.Millisecond) profiler.Stop() f, err := os.Open(memProfilePath) Expect(err).NotTo(HaveOccurred()) _, err = parser.NewHeapProfParser(f) Expect(err).NotTo(HaveOccurred()) }) It("panics when there is an error", func() { filePath := "/tmp/asdf/asdf.pprof" profiler := profiler.New("", filePath, 1*time.Millisecond, logger) Expect(profiler.Profile).To(Panic()) }) }) Describe("Stop", func() { It("closes the both profile file handles", func() { profiler := profiler.New(cpuProfilePath, memProfilePath, 1*time.Millisecond, logger) profiler.Profile()