Skip to content

Commit ea435bc

Browse files
committed
Fix truncated CPU profiles
1 parent 4837be6 commit ea435bc

13 files changed

+35
-14
lines changed

‎pkg/pprof/fix_go_profile.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ func FixGoProfile(p *profilev1.Profile) *profilev1.Profile {
2020
// truncated stack traces, if any. Note that repaired stacks
2121
// are not deduplicated, so the caller need to normalize the
2222
if MayHaveGoHeapTruncatedStacktraces(p) {
23-
RepairGoHeapTruncatedStacktraces(p)
23+
RepairGoTruncatedStacktraces(p)
2424
}
2525
return p
2626
}

‎pkg/pprof/fix_go_profile_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import (
1010
)
1111

1212
func Test_FixGoProfile(t *testing.T) {
13-
p, err := OpenFile("testdata/goheapfix/heap_go_truncated_4.pb.gz")
13+
p, err := OpenFile("testdata/gotruncatefix/heap_go_truncated_4.pb.gz")
1414
require.NoError(t, err)
1515

1616
f := FixGoProfile(p.Profile)

‎pkg/pprof/fix_go_heap_truncated.go renamed to ‎pkg/pprof/fix_go_truncated.go

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,20 @@ const (
2323
// MayHaveGoHeapTruncatedStacktraces reports whether there are
2424
// any chances that the profile may have truncated stack traces.
2525
func MayHaveGoHeapTruncatedStacktraces(p *profilev1.Profile) bool {
26-
if !hasGoHeapSampleTypes(p) {
26+
var minDepth = 0
27+
28+
if hasGoHeapSampleTypes(p) {
29+
// TODO: Go heap profiles in Go 1.23 have a depth limit of 128 frames. At some point we can probably increase/remove this
30+
minDepth = 32
31+
} else if hasGoCPUSampleTypes(p) {
32+
minDepth = 64
33+
} else {
2734
return false
2835
}
29-
// Some truncated stacks have depth less than the depth limit (32).
30-
const minDepth = 28
36+
37+
// Some truncated stacks have depth less than the depth limit.
38+
minDepth -= 3
39+
3140
for _, s := range p.Sample {
3241
if len(s.LocationId) >= minDepth {
3342
return true
@@ -50,7 +59,18 @@ func hasGoHeapSampleTypes(p *profilev1.Profile) bool {
5059
return false
5160
}
5261

53-
// RepairGoHeapTruncatedStacktraces repairs truncated stack traces
62+
func hasGoCPUSampleTypes(p *profilev1.Profile) bool {
63+
for _, st := range p.SampleType {
64+
switch p.StringTable[st.Type] {
65+
case
66+
"cpu":
67+
return true
68+
}
69+
}
70+
return false
71+
}
72+
73+
// RepairGoTruncatedStacktraces repairs truncated stack traces
5474
// in Go heap profiles.
5575
//
5676
// Go heap profile has a depth limit of 32 frames, which often
@@ -66,7 +86,7 @@ func hasGoHeapSampleTypes(p *profilev1.Profile) bool {
6686
// one by at least 16 frames in a row from the top, and has frames
6787
// above its root, stack S considered truncated, and the missing part
6888
// is copied from R.
69-
func RepairGoHeapTruncatedStacktraces(p *profilev1.Profile) {
89+
func RepairGoTruncatedStacktraces(p *profilev1.Profile) {
7090
// Group stack traces by bottom (closest to the root) locations.
7191
// Typically, there are very few groups (a hundred or two).
7292
samples, groups := split(p)

‎pkg/pprof/fix_go_heap_truncated_test.go renamed to ‎pkg/pprof/fix_go_truncated_test.go

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,23 +8,24 @@ import (
88
)
99

1010
func Benchmark_RepairGoTruncatedStacktraces(b *testing.B) {
11-
p, err := OpenFile("testdata/goheapfix/heap_go_truncated_3.pb.gz")
11+
p, err := OpenFile("testdata/gotruncatefix/heap_go_truncated_3.pb.gz")
1212
require.NoError(b, err)
1313
b.ResetTimer()
1414
b.ReportAllocs()
1515
for i := 0; i < b.N; i++ {
16-
RepairGoHeapTruncatedStacktraces(FixGoProfile(p.CloneVT()))
16+
RepairGoTruncatedStacktraces(FixGoProfile(p.CloneVT()))
1717
}
1818
}
1919

2020
func Test_UpdateFixtures_RepairGoTruncatedStacktraces(t *testing.T) {
2121
t.Skip()
2222
t.Helper()
2323
paths := []string{
24-
"testdata/goheapfix/heap_go_truncated_1.pb.gz", // Cortex.
25-
"testdata/goheapfix/heap_go_truncated_2.pb.gz", // Cortex.
26-
"testdata/goheapfix/heap_go_truncated_3.pb.gz", // Loki. Pathological.
27-
"testdata/goheapfix/heap_go_truncated_4.pb.gz", // Pyroscope.
24+
"testdata/gotruncatefix/heap_go_truncated_1.pb.gz", // Cortex.
25+
"testdata/gotruncatefix/heap_go_truncated_2.pb.gz", // Cortex.
26+
"testdata/gotruncatefix/heap_go_truncated_3.pb.gz", // Loki. Pathological.
27+
"testdata/gotruncatefix/heap_go_truncated_4.pb.gz", // Pyroscope.
28+
"testdata/gotruncatefix/cpu_go_truncated_1.pb.gz", // Mimir Querier
2829
}
2930
for _, path := range paths {
3031
func() {
@@ -34,7 +35,7 @@ func Test_UpdateFixtures_RepairGoTruncatedStacktraces(t *testing.T) {
3435
require.NoError(t, err, path)
3536
defer f.Close()
3637
p.Profile = FixGoProfile(p.Profile)
37-
RepairGoHeapTruncatedStacktraces(p.Profile)
38+
RepairGoTruncatedStacktraces(p.Profile)
3839
_, err = p.WriteTo(f)
3940
require.NoError(t, err, path)
4041
}()
Binary file not shown.

0 commit comments

Comments
 (0)