func requireProgTimes(s *gcstats.GcStats) { if !s.HaveProgTimes() { fmt.Fprintln(os.Stderr, "This analysis requires program execution times, which are missing from\n"+ "this GC trace. Please see 'go doc gcstats' for how to enable these.") os.Exit(1) } }
func doMMU(s *gcstats.GcStats) { // 1e9 ns = 1000 ms windows := vec.Logspace(-3, 0, samples, 10) plot := newPlot("granularity", windows, "--style", "mmu") plot.addSeries("MMU", func(window float64) float64 { return s.MMU(int(window * 1e9)) }) showPlot(plot) }
func doStopCDF(s *gcstats.GcStats, kdes map[gcstats.PhaseKind]*stats.KDE) { xs := jointAxis(kdes, float64(s.MaxPause())/1e9) for _, kde := range kdes { kde.Kernel = stats.DeltaKernel } plot := newPlot("pause time", xs) for kind := gcstats.PhaseSweepTerm; kind <= gcstats.PhaseMultiple; kind++ { if kde := kdes[kind]; kde != nil { plot.addSeries(kind.String(), kde.CDF) } } showPlot(plot) }
func stopKDEs(s *gcstats.GcStats) map[gcstats.PhaseKind]*stats.KDE { stops := s.Stops() times := make(map[gcstats.PhaseKind]stats.Sample) for _, stop := range stops { s := times[stop.Kind] s.Xs = append(s.Xs, float64(stop.Duration)/1e9) times[stop.Kind] = s } kdes := make(map[gcstats.PhaseKind]*stats.KDE) for kind, sample := range times { // XXX Bandwidth kdes[kind] = &stats.KDE{ Sample: sample, //Bandwidth: stats.FixedBandwidth(100000), BoundaryMethod: stats.BoundaryReflect, BoundaryMax: math.Inf(1), } } return kdes }
func doMUDMap(s *gcstats.GcStats) { windows := ints(vec.Logspace(6, 9, 100, 10)) muds := make([]*gcstats.MUD, len(windows)) for i, windowNS := range windows { muds[i] = s.MutatorUtilizationDistribution(windowNS) } // gnuplot "nonuniform matrix" format fmt.Printf("%d ", len(windows)+1) for _, windowNS := range windows { fmt.Printf("%d ", windowNS) } fmt.Print("\n") utils := vec.Linspace(0, 1, 100) for _, util := range utils { fmt.Printf("%g ", util) for _, mud := range muds { fmt.Printf("%g ", mud.CDF(util)) } fmt.Print("\n") } }
func doMUT(s *gcstats.GcStats) { windows := vec.Logspace(-3, 0, samples, 10) muds := make(map[float64]*gcstats.MUD) for _, window := range windows { muds[window] = s.MutatorUtilizationDistribution(int(window * 1e9)) } plot := newPlot("granularity", windows, "--style", "mut") type config struct { label string x float64 } for _, c := range []config{ {"100%ile", 0}, {"99.9%ile", 0.001}, {"99%ile", 0.01}, {"90%ile", 0.1}, } { plot.addSeries(c.label, func(x float64) float64 { return muds[x].InvCDF(c.x) }) } showPlot(plot) }
func doSummary(s *gcstats.GcStats) { // Pause time: Max, 99th %ile, 95th %ile, mean // Mutator utilization // 50ms mutator utilization: Min, 1st %ile, 5th %ile pauseTimes := stats.Sample{Xs: []float64{}} for _, stop := range s.Stops() { pauseTimes.Xs = append(pauseTimes.Xs, float64(stop.Duration)) } pauseTimes.Sort() fmt.Print("Pause times: max=", ns(pauseTimes.Percentile(1)), " 99th %ile=", ns(pauseTimes.Percentile(.99)), " 95th %ile=", ns(pauseTimes.Percentile(.95)), " mean=", ns(pauseTimes.Mean()), "\n") if s.HaveProgTimes() { fmt.Print("Mutator utilization: ", pct(s.MutatorUtilization()), "\n") fmt.Print("50ms mutator utilization: min=", pct(s.MMUs([]int{50000000})[0]), "\n") } }