mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
runtime/pprof: fix goroutine leak profile tests for noopt
The goroutine leak profile tests currently rely on a function being inlined, which results in a slightly different representation in the pprof proto. This function is not inlined on the noopt builder. Disable inlining of the one function which could be inlined to align but the regular and noopt builder versions of this test. We're not interested in testing the inlining functionality of profiles with this test, we care about certain stack frames appearing in a certain order. This also simplifies a bunch of the checking in the test. Cq-Include-Trybots: luci.golang.try:gotip-linux-amd64-noopt Change-Id: I28902cc4c9fae32d1e3fa41b93b00c3be4d6074a Reviewed-on: https://go-review.googlesource.com/c/go/+/720100 Reviewed-by: Keith Randall <khr@golang.org> Reviewed-by: Keith Randall <khr@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
This commit is contained in:
parent
4684a26c26
commit
625d8e9b9c
1 changed files with 15 additions and 22 deletions
|
|
@ -1569,6 +1569,9 @@ func containsCountsLabels(prof *profile.Profile, countLabels map[int64]map[strin
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Inlining disabled to make identification simpler.
|
||||||
|
//
|
||||||
|
//go:noinline
|
||||||
func goroutineLeakExample() {
|
func goroutineLeakExample() {
|
||||||
<-make(chan struct{})
|
<-make(chan struct{})
|
||||||
panic("unreachable")
|
panic("unreachable")
|
||||||
|
|
@ -1595,12 +1598,12 @@ func TestGoroutineLeakProfileConcurrency(t *testing.T) {
|
||||||
|
|
||||||
checkFrame := func(i int, j int, locations []*profile.Location, expectedFunctionName string) {
|
checkFrame := func(i int, j int, locations []*profile.Location, expectedFunctionName string) {
|
||||||
if len(locations) <= i {
|
if len(locations) <= i {
|
||||||
t.Errorf("leaked goroutine stack locations out of range at %d of %d", i+1, len(locations))
|
t.Errorf("leaked goroutine stack locations: out of range index %d, length %d", i, len(locations))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
location := locations[i]
|
location := locations[i]
|
||||||
if len(location.Line) <= j {
|
if len(location.Line) <= j {
|
||||||
t.Errorf("leaked goroutine stack location lines out of range at %d of %d", j+1, len(location.Line))
|
t.Errorf("leaked goroutine stack location lines: out of range index %d, length %d", j, len(location.Line))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if location.Line[j].Function.Name != expectedFunctionName {
|
if location.Line[j].Function.Name != expectedFunctionName {
|
||||||
|
|
@ -1650,26 +1653,7 @@ func TestGoroutineLeakProfileConcurrency(t *testing.T) {
|
||||||
t.Errorf("expected %d leaked goroutines with specific stack configurations, but found %d", leakCount, pc)
|
t.Errorf("expected %d leaked goroutines with specific stack configurations, but found %d", leakCount, pc)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
switch len(locations) {
|
if len(locations) < 4 || len(locations) > 5 {
|
||||||
case 4:
|
|
||||||
// We expect a receive operation. This is the typical stack.
|
|
||||||
checkFrame(0, 0, locations, "runtime.gopark")
|
|
||||||
checkFrame(1, 0, locations, "runtime.chanrecv")
|
|
||||||
checkFrame(2, 0, locations, "runtime.chanrecv1")
|
|
||||||
switch len(locations[3].Line) {
|
|
||||||
case 2:
|
|
||||||
// Running `go func() { goroutineLeakExample() }()` will produce a stack with 2 lines.
|
|
||||||
// The anonymous function will have the call to goroutineLeakExample inlined.
|
|
||||||
checkFrame(3, 1, locations, "runtime/pprof.TestGoroutineLeakProfileConcurrency.func5")
|
|
||||||
fallthrough
|
|
||||||
case 1:
|
|
||||||
// Running `go goroutineLeakExample()` will produce a stack with 1 line.
|
|
||||||
checkFrame(3, 0, locations, "runtime/pprof.goroutineLeakExample")
|
|
||||||
default:
|
|
||||||
t.Errorf("leaked goroutine stack location expected 1 or 2 lines in the 4th location but found %d", len(locations[3].Line))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
message := fmt.Sprintf("leaked goroutine stack expected 4 or 5 locations but found %d", len(locations))
|
message := fmt.Sprintf("leaked goroutine stack expected 4 or 5 locations but found %d", len(locations))
|
||||||
for _, location := range locations {
|
for _, location := range locations {
|
||||||
for _, line := range location.Line {
|
for _, line := range location.Line {
|
||||||
|
|
@ -1677,6 +1661,15 @@ func TestGoroutineLeakProfileConcurrency(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
t.Errorf("%s", message)
|
t.Errorf("%s", message)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// We expect a receive operation. This is the typical stack.
|
||||||
|
checkFrame(0, 0, locations, "runtime.gopark")
|
||||||
|
checkFrame(1, 0, locations, "runtime.chanrecv")
|
||||||
|
checkFrame(2, 0, locations, "runtime.chanrecv1")
|
||||||
|
checkFrame(3, 0, locations, "runtime/pprof.goroutineLeakExample")
|
||||||
|
if len(locations) == 5 {
|
||||||
|
checkFrame(4, 0, locations, "runtime/pprof.TestGoroutineLeakProfileConcurrency.func5")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue