From: Dmitriy Vyukov Date: Sat, 30 Aug 2014 18:38:54 +0000 (+0400) Subject: runtime/pprof: make CPU profiling tests more robust X-Git-Tag: go1.4beta1~604 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=2fd62a42b48ffc111aebdc4a191d705248888fc1;p=gostls13.git runtime/pprof: make CPU profiling tests more robust Under the race detector most of the samples go into race runtime, because of that freebsd race builder constantly fails on this test. LGTM=bradfitz, rsc R=golang-codereviews, bradfitz, rsc CC=golang-codereviews, minux https://golang.org/cl/133370043 --- diff --git a/src/pkg/runtime/pprof/pprof_test.go b/src/pkg/runtime/pprof/pprof_test.go index 99c27ba96c..3c59fe76cb 100644 --- a/src/pkg/runtime/pprof/pprof_test.go +++ b/src/pkg/runtime/pprof/pprof_test.go @@ -9,7 +9,6 @@ package pprof_test import ( "bytes" "fmt" - "hash/crc32" "math/big" "os/exec" "regexp" @@ -22,35 +21,65 @@ import ( "unsafe" ) -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 cpuHogger(f func()) { + // We only need to get one 100 Hz clock tick, so we've got + // a 25x safety buffer. + // But do at least 500 iterations (which should take about 100ms), + // otherwise TestCPUProfileMultithreaded can fail if only one + // thread is scheduled during the 250ms period. + t0 := time.Now() + for i := 0; i < 500 || time.Since(t0) < 250*time.Millisecond; i++ { + f() + } +} + +var ( + salt1 = 0 + salt2 = 0 +) + +// The actual CPU hogging function. +// Must not call other functions nor access heap/globals in the loop, +// otherwise under race detector the samples will be in the race runtime. +func cpuHog1() { + foo := salt1 + for i := 0; i < 1e5; i++ { + if foo > 0 { + foo *= foo + } else { + foo *= foo + 1 + } + } + salt1 = foo +} + +func cpuHog2() { + foo := salt2 + for i := 0; i < 1e5; i++ { + if foo > 0 { + foo *= foo + } else { + foo *= foo + 2 } + } + salt2 = foo +} + +func TestCPUProfile(t *testing.T) { + testCPUProfile(t, []string{"runtime/pprof_test.cpuHog1"}, func() { + cpuHogger(cpuHog1) }) } func TestCPUProfileMultithreaded(t *testing.T) { - buf := make([]byte, 100000) defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(2)) - testCPUProfile(t, []string{"crc32.ChecksumIEEE", "crc32.Update"}, func() { + testCPUProfile(t, []string{"runtime/pprof_test.cpuHog1", "runtime/pprof_test.cpuHog2"}, func() { c := make(chan int) go func() { - for i := 0; i < 2000; i++ { - crc32.Update(0, crc32.IEEETable, buf) - } + cpuHogger(cpuHog1) 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) - } + cpuHogger(cpuHog2) <-c }) } @@ -110,7 +139,7 @@ func testCPUProfile(t *testing.T, need []string, f func()) { f() StopCPUProfile() - // Check that profile is well formed and contains ChecksumIEEE. + // Check that profile is well formed and contains need. have := make([]uintptr, len(need)) parseProfile(t, prof.Bytes(), func(count uintptr, stk []uintptr) { for _, pc := range stk {