func TestMutexProfile(t *testing.T) { old := runtime.SetMutexProfileFraction(1) defer runtime.SetMutexProfileFraction(old) if old != 0 { t.Fatalf("need MutexProfileRate 0, got %d", old) } blockMutex() var w bytes.Buffer Lookup("mutex").WriteTo(&w, 1) prof := w.String() if !strings.HasPrefix(prof, "--- mutex:\ncycles/second=") { t.Errorf("Bad profile header:\n%v", prof) } prof = strings.Trim(prof, "\n") lines := strings.Split(prof, "\n") if len(lines) != 6 { t.Errorf("expected 6 lines, got %d %q\n%s", len(lines), prof, prof) } if len(lines) < 6 { return } // checking that the line is like "35258904 1 @ 0x48288d 0x47cd28 0x458931" r2 := `^\d+ 1 @(?: 0x[[:xdigit:]]+)+` //r2 := "^[0-9]+ 1 @ 0x[0-9a-f x]+$" if ok, err := regexp.MatchString(r2, lines[3]); err != nil || !ok { t.Errorf("%q didn't match %q", lines[3], r2) } r3 := "^#.*runtime/pprof_test.blockMutex.*$" if ok, err := regexp.MatchString(r3, lines[5]); err != nil || !ok { t.Errorf("%q didn't match %q", lines[5], r3) } }
func TestMutex(t *testing.T) { if n := runtime.SetMutexProfileFraction(1); n != 0 { t.Logf("got mutexrate %d expected 0", n) } defer runtime.SetMutexProfileFraction(0) m := new(Mutex) c := make(chan bool) for i := 0; i < 10; i++ { go HammerMutex(m, 1000, c) } for i := 0; i < 10; i++ { <-c } }
// writeMutex writes the current mutex profile to w. func writeMutex(w io.Writer, debug int) error { // TODO(pjw): too much common code with writeBlock. FIX! var p []runtime.BlockProfileRecord n, ok := runtime.MutexProfile(nil) for { p = make([]runtime.BlockProfileRecord, n+50) n, ok = runtime.MutexProfile(p) if ok { p = p[:n] break } } sort.Slice(p, func(i, j int) bool { return p[i].Cycles > p[j].Cycles }) b := bufio.NewWriter(w) var tw *tabwriter.Writer w = b if debug > 0 { tw = tabwriter.NewWriter(w, 1, 8, 1, '\t', 0) w = tw } fmt.Fprintf(w, "--- mutex:\n") fmt.Fprintf(w, "cycles/second=%v\n", runtime_cyclesPerSecond()) fmt.Fprintf(w, "sampling period=%d\n", runtime.SetMutexProfileFraction(-1)) for i := range p { r := &p[i] fmt.Fprintf(w, "%v %v @", r.Cycles, r.Count) for _, pc := range r.Stack() { fmt.Fprintf(w, " %#x", pc) } fmt.Fprint(w, "\n") if debug > 0 { printStackRecord(w, r.Stack(), true) } } if tw != nil { tw.Flush() } return b.Flush() }
// before runs before all testing. func (m *M) before() { if *memProfileRate > 0 { runtime.MemProfileRate = *memProfileRate } if *cpuProfile != "" { f, err := os.Create(toOutputDir(*cpuProfile)) if err != nil { fmt.Fprintf(os.Stderr, "testing: %s", err) return } if err := m.deps.StartCPUProfile(f); err != nil { fmt.Fprintf(os.Stderr, "testing: can't start cpu profile: %s", err) f.Close() return } // Could save f so after can call f.Close; not worth the effort. } if *traceFile != "" { f, err := os.Create(toOutputDir(*traceFile)) if err != nil { fmt.Fprintf(os.Stderr, "testing: %s", err) return } if err := trace.Start(f); err != nil { fmt.Fprintf(os.Stderr, "testing: can't start tracing: %s", err) f.Close() return } // Could save f so after can call f.Close; not worth the effort. } if *blockProfile != "" && *blockProfileRate >= 0 { runtime.SetBlockProfileRate(*blockProfileRate) } if *mutexProfile != "" && *mutexProfileFraction >= 0 { runtime.SetMutexProfileFraction(*mutexProfileFraction) } if *coverProfile != "" && cover.Mode == "" { fmt.Fprintf(os.Stderr, "testing: cannot use -test.coverprofile because test binary was not built with coverage enabled\n") os.Exit(2) } }