mirror of
https://github.com/golang/go
synced 2024-11-12 07:40:23 -07:00
test: improve runtime/pprof tests for gccgo
In the CPU profile tests for gccgo, check to make sure that the runtime's sigprof handler itself doesn't appear in the profile. Add a "skip if gccgo" guard to one testpoint. Updates #26595 Change-Id: I92a44161d61f17b9305ce09532134edd229745a7 Reviewed-on: https://go-review.googlesource.com/126316 Run-TryBot: Than McIntosh <thanm@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Ian Lance Taylor <iant@golang.org>
This commit is contained in:
parent
dbd8af7472
commit
88206b8931
@ -72,15 +72,24 @@ func cpuHog2(x int) int {
|
||||
return foo
|
||||
}
|
||||
|
||||
// Return a list of functions that we don't want to ever appear in CPU
|
||||
// profiles. For gccgo, that list includes the sigprof handler itself.
|
||||
func avoidFunctions() []string {
|
||||
if runtime.Compiler == "gccgo" {
|
||||
return []string{"runtime.sigprof"}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestCPUProfile(t *testing.T) {
|
||||
testCPUProfile(t, stackContains, []string{"runtime/pprof.cpuHog1"}, func(dur time.Duration) {
|
||||
testCPUProfile(t, stackContains, []string{"runtime/pprof.cpuHog1"}, avoidFunctions(), func(dur time.Duration) {
|
||||
cpuHogger(cpuHog1, &salt1, dur)
|
||||
})
|
||||
}
|
||||
|
||||
func TestCPUProfileMultithreaded(t *testing.T) {
|
||||
defer runtime.GOMAXPROCS(runtime.GOMAXPROCS(2))
|
||||
testCPUProfile(t, stackContains, []string{"runtime/pprof.cpuHog1", "runtime/pprof.cpuHog2"}, func(dur time.Duration) {
|
||||
testCPUProfile(t, stackContains, []string{"runtime/pprof.cpuHog1", "runtime/pprof.cpuHog2"}, avoidFunctions(), func(dur time.Duration) {
|
||||
c := make(chan int)
|
||||
go func() {
|
||||
cpuHogger(cpuHog1, &salt1, dur)
|
||||
@ -92,7 +101,7 @@ func TestCPUProfileMultithreaded(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCPUProfileInlining(t *testing.T) {
|
||||
testCPUProfile(t, stackContains, []string{"runtime/pprof.inlinedCallee", "runtime/pprof.inlinedCaller"}, func(dur time.Duration) {
|
||||
testCPUProfile(t, stackContains, []string{"runtime/pprof.inlinedCallee", "runtime/pprof.inlinedCaller"}, avoidFunctions(), func(dur time.Duration) {
|
||||
cpuHogger(inlinedCaller, &salt1, dur)
|
||||
})
|
||||
}
|
||||
@ -132,7 +141,7 @@ func parseProfile(t *testing.T, valBytes []byte, f func(uintptr, []*profile.Loca
|
||||
|
||||
// testCPUProfile runs f under the CPU profiler, checking for some conditions specified by need,
|
||||
// as interpreted by matches.
|
||||
func testCPUProfile(t *testing.T, matches matchFunc, need []string, f func(dur time.Duration)) {
|
||||
func testCPUProfile(t *testing.T, matches matchFunc, need []string, avoid []string, f func(dur time.Duration)) {
|
||||
switch runtime.GOOS {
|
||||
case "darwin":
|
||||
switch runtime.GOARCH {
|
||||
@ -171,7 +180,7 @@ func testCPUProfile(t *testing.T, matches matchFunc, need []string, f func(dur t
|
||||
f(duration)
|
||||
StopCPUProfile()
|
||||
|
||||
if profileOk(t, need, matches, prof, duration) {
|
||||
if profileOk(t, matches, need, avoid, prof, duration) {
|
||||
return
|
||||
}
|
||||
|
||||
@ -218,11 +227,13 @@ func stackContains(spec string, count uintptr, stk []*profile.Location, labels m
|
||||
|
||||
type matchFunc func(spec string, count uintptr, stk []*profile.Location, labels map[string][]string) bool
|
||||
|
||||
func profileOk(t *testing.T, need []string, matches matchFunc, prof bytes.Buffer, duration time.Duration) (ok bool) {
|
||||
func profileOk(t *testing.T, matches matchFunc, need []string, avoid []string, prof bytes.Buffer, duration time.Duration) (ok bool) {
|
||||
ok = true
|
||||
|
||||
// Check that profile is well formed and contains need.
|
||||
// Check that profile is well formed, contains 'need', and does not contain
|
||||
// anything from 'avoid'.
|
||||
have := make([]uintptr, len(need))
|
||||
avoidSamples := make([]uintptr, len(avoid))
|
||||
var samples uintptr
|
||||
var buf bytes.Buffer
|
||||
parseProfile(t, prof.Bytes(), func(count uintptr, stk []*profile.Location, labels map[string][]string) {
|
||||
@ -234,6 +245,15 @@ func profileOk(t *testing.T, need []string, matches matchFunc, prof bytes.Buffer
|
||||
have[i] += count
|
||||
}
|
||||
}
|
||||
for i, name := range avoid {
|
||||
for _, loc := range stk {
|
||||
for _, line := range loc.Line {
|
||||
if strings.Contains(line.Function.Name, name) {
|
||||
avoidSamples[i] += count
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fmt.Fprintf(&buf, "\n")
|
||||
})
|
||||
t.Logf("total %d CPU profile samples collected:\n%s", samples, buf.String())
|
||||
@ -256,6 +276,14 @@ func profileOk(t *testing.T, need []string, matches matchFunc, prof bytes.Buffer
|
||||
ok = false
|
||||
}
|
||||
|
||||
for i, name := range avoid {
|
||||
bad := avoidSamples[i]
|
||||
if bad != 0 {
|
||||
t.Logf("found %d samples in avoid-function %s\n", bad, name)
|
||||
ok = false
|
||||
}
|
||||
}
|
||||
|
||||
if len(need) == 0 {
|
||||
return ok
|
||||
}
|
||||
@ -323,6 +351,9 @@ func TestCPUProfileWithFork(t *testing.T) {
|
||||
// If it did, it would see inconsistent state and would either record an incorrect stack
|
||||
// or crash because the stack was malformed.
|
||||
func TestGoroutineSwitch(t *testing.T) {
|
||||
if runtime.Compiler == "gccgo" {
|
||||
t.Skip("not applicable for gccgo")
|
||||
}
|
||||
// How much to try. These defaults take about 1 seconds
|
||||
// on a 2012 MacBook Pro. The ones in short mode take
|
||||
// about 0.1 seconds.
|
||||
@ -382,7 +413,7 @@ func fprintStack(w io.Writer, stk []*profile.Location) {
|
||||
|
||||
// Test that profiling of division operations is okay, especially on ARM. See issue 6681.
|
||||
func TestMathBigDivide(t *testing.T) {
|
||||
testCPUProfile(t, nil, nil, func(duration time.Duration) {
|
||||
testCPUProfile(t, nil, nil, nil, func(duration time.Duration) {
|
||||
t := time.After(duration)
|
||||
pi := new(big.Int)
|
||||
for {
|
||||
@ -411,7 +442,7 @@ func stackContainsAll(spec string, count uintptr, stk []*profile.Location, label
|
||||
}
|
||||
|
||||
func TestMorestack(t *testing.T) {
|
||||
testCPUProfile(t, stackContainsAll, []string{"runtime.newstack,runtime/pprof.growstack"}, func(duration time.Duration) {
|
||||
testCPUProfile(t, stackContainsAll, []string{"runtime.newstack,runtime/pprof.growstack"}, avoidFunctions(), func(duration time.Duration) {
|
||||
t := time.After(duration)
|
||||
c := make(chan bool)
|
||||
for {
|
||||
@ -913,7 +944,7 @@ func stackContainsLabeled(spec string, count uintptr, stk []*profile.Location, l
|
||||
}
|
||||
|
||||
func TestCPUProfileLabel(t *testing.T) {
|
||||
testCPUProfile(t, stackContainsLabeled, []string{"runtime/pprof.cpuHogger;key=value"}, func(dur time.Duration) {
|
||||
testCPUProfile(t, stackContainsLabeled, []string{"runtime/pprof.cpuHogger;key=value"}, avoidFunctions(), func(dur time.Duration) {
|
||||
Do(context.Background(), Labels("key", "value"), func(context.Context) {
|
||||
cpuHogger(cpuHog1, &salt1, dur)
|
||||
})
|
||||
@ -924,7 +955,7 @@ func TestLabelRace(t *testing.T) {
|
||||
// Test the race detector annotations for synchronization
|
||||
// between settings labels and consuming them from the
|
||||
// profile.
|
||||
testCPUProfile(t, stackContainsLabeled, []string{"runtime/pprof.cpuHogger;key=value"}, func(dur time.Duration) {
|
||||
testCPUProfile(t, stackContainsLabeled, []string{"runtime/pprof.cpuHogger;key=value"}, nil, func(dur time.Duration) {
|
||||
start := time.Now()
|
||||
var wg sync.WaitGroup
|
||||
for time.Since(start) < dur {
|
||||
|
Loading…
Reference in New Issue
Block a user