diff options
Diffstat (limited to 'src/pkg/runtime/pprof/pprof_test.go')
| -rw-r--r-- | src/pkg/runtime/pprof/pprof_test.go | 82 |
1 files changed, 66 insertions, 16 deletions
diff --git a/src/pkg/runtime/pprof/pprof_test.go b/src/pkg/runtime/pprof/pprof_test.go index 94d19f741c..995c2fe68d 100644 --- a/src/pkg/runtime/pprof/pprof_test.go +++ b/src/pkg/runtime/pprof/pprof_test.go @@ -19,6 +19,38 @@ import ( ) func TestCPUProfile(t *testing.T) { + buf := make([]byte, 100000) + testCPUProfile(t, []string{"crc32.ChecksumIEEE"}, func() { + // This loop takes about a quarter second on a 2 GHz laptop. + // We only need to get one 100 Hz clock tick, so we've got + // a 25x safety buffer. + for i := 0; i < 1000; i++ { + crc32.ChecksumIEEE(buf) + } + }) +} + +func TestCPUProfileMultithreaded(t *testing.T) { + buf := make([]byte, 100000) + defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(2)) + testCPUProfile(t, []string{"crc32.ChecksumIEEE", "crc32.Update"}, func() { + c := make(chan int) + go func() { + for i := 0; i < 2000; i++ { + crc32.Update(0, crc32.IEEETable, buf) + } + c <- 1 + }() + // This loop takes about a quarter second on a 2 GHz laptop. + // We only need to get one 100 Hz clock tick, so we've got + // a 25x safety buffer. + for i := 0; i < 2000; i++ { + crc32.ChecksumIEEE(buf) + } + }) +} + +func testCPUProfile(t *testing.T, need []string, f func()) { switch runtime.GOOS { case "darwin": out, err := exec.Command("uname", "-a").CombinedOutput() @@ -27,26 +59,16 @@ func TestCPUProfile(t *testing.T) { } vers := string(out) t.Logf("uname -a: %v", vers) - // Lion uses "Darwin Kernel Version 11". - if strings.Contains(vers, "Darwin Kernel Version 10") && strings.Contains(vers, "RELEASE_X86_64") { - t.Skip("skipping test on known-broken kernel (64-bit Leopard / Snow Leopard)") - } case "plan9": // unimplemented return } - buf := make([]byte, 100000) var prof bytes.Buffer if err := StartCPUProfile(&prof); err != nil { t.Fatal(err) } - // This loop takes about a quarter second on a 2 GHz laptop. - // We only need to get one 100 Hz clock tick, so we've got - // a 25x safety buffer. - for i := 0; i < 1000; i++ { - crc32.ChecksumIEEE(buf) - } + f() StopCPUProfile() // Convert []byte to []uintptr. @@ -56,6 +78,10 @@ func TestCPUProfile(t *testing.T) { val = val[:l] if l < 13 { + if runtime.GOOS == "darwin" { + t.Logf("ignoring failure on OS X; see golang.org/issue/6047") + return + } t.Fatalf("profile too short: %#x", val) } @@ -69,7 +95,7 @@ func TestCPUProfile(t *testing.T) { } // Check that profile is well formed and contains ChecksumIEEE. - found := false + have := make([]uintptr, len(need)) for len(val) > 0 { if len(val) < 2 || val[0] < 1 || val[1] < 1 || uintptr(len(val)) < 2+val[1] { t.Fatalf("malformed profile. leftover: %#x", val) @@ -79,14 +105,38 @@ func TestCPUProfile(t *testing.T) { if f == nil { continue } - if strings.Contains(f.Name(), "ChecksumIEEE") { - found = true + for i, name := range need { + if strings.Contains(f.Name(), name) { + have[i] += val[0] + } } } val = val[2+val[1]:] } - if !found { - t.Fatal("did not find ChecksumIEEE in the profile") + var total uintptr + for i, name := range need { + total += have[i] + t.Logf("%s: %d\n", name, have[i]) + } + ok := true + if total == 0 { + t.Logf("no CPU profile samples collected") + ok = false + } + min := total / uintptr(len(have)) / 2 + for i, name := range need { + if have[i] < min { + t.Logf("%s has %d samples out of %d, want at least %d, ideally %d", name, have[i], total, min, total/uintptr(len(have))) + ok = false + } + } + + if !ok { + if runtime.GOOS == "darwin" { + t.Logf("ignoring failure on OS X; see golang.org/issue/6047") + return + } + t.FailNow() } } |
