Skip to content

Commit 181f95a

Browse files
authored
fix(godeltaprof): fix mutex tests on gotip (#108)
Fixes #103 This PR fixes an issue when a heap/mutex profile has a record with equal stack (by accumulating values for duplicate stacks before delta computation). The issue was found in tests for mutex(golang started to produce two profile records for the same mutex ( see the linked issue for more info)) I'm not sure if it is possible to trigger the issue for heap. The PR turned up big because of refactored test helpers for reuse. I can split PR into 2 or 3 smaller ones if needed. This PR also drops support for go16, go17 as I wanted to use generics in prof/map.go goos: darwin goarch: arm64 pkg: github.com/grafana/pyroscope-go/godeltaprof/compat │ old.txt │ new.txt │ │ sec/op │ sec/op vs base │ HeapCompression-8 691.1µ ± 0% 729.8µ ± 65% +5.59% (p=0.002 n=6) MutexCompression/ScalerMutexProfile-8 640.6µ ± 1% 693.8µ ± 9% +8.30% (p=0.002 n=6) MutexCompression/ScalerBlockProfile-8 643.2µ ± 1% 690.3µ ± 1% +7.33% (p=0.002 n=6) HeapDelta-8 76.26µ ± 1% 113.92µ ± 2% +49.38% (p=0.002 n=6) MutexDelta/ScalerMutexProfile-8 48.98µ ± 1% 81.11µ ± 2% +65.59% (p=0.002 n=6) MutexDelta/ScalerBlockProfile-8 49.03µ ± 1% 81.14µ ± 1% +65.49% (p=0.002 n=6) geomean 193.3µ 253.0µ +30.87% │ old.txt │ new.txt │ │ B/op │ B/op vs base │ HeapCompression-8 974.1Ki ± 0% 973.9Ki ± 0% -0.03% (p=0.002 n=6) MutexCompression/ScalerMutexProfile-8 974.6Ki ± 0% 974.3Ki ± 0% -0.02% (p=0.002 n=6) MutexCompression/ScalerBlockProfile-8 974.6Ki ± 0% 974.3Ki ± 0% -0.03% (p=0.002 n=6) HeapDelta-8 333.00 ± 0% 53.00 ± 0% -84.08% (p=0.002 n=6) MutexDelta/ScalerMutexProfile-8 312.00 ± 0% 30.00 ± 0% -90.38% (p=0.002 n=6) MutexDelta/ScalerBlockProfile-8 312.00 ± 0% 30.00 ± 0% -90.38% (p=0.002 n=6) geomean 17.42Ki 5.874Ki -66.28% │ old.txt │ new.txt │ │ allocs/op │ allocs/op vs base │ HeapCompression-8 788.0 ± 0% 787.0 ± 0% -0.13% (p=0.002 n=6) MutexCompression/ScalerMutexProfile-8 788.0 ± 0% 787.0 ± 0% -0.13% (p=0.002 n=6) MutexCompression/ScalerBlockProfile-8 788.0 ± 0% 787.0 ± 0% -0.13% (p=0.002 n=6) HeapDelta-8 2.000 ± 0% 1.000 ± 0% -50.00% (p=0.002 n=6) MutexDelta/ScalerMutexProfile-8 2.000 ± 0% 1.000 ± 0% -50.00% (p=0.002 n=6) MutexDelta/ScalerBlockProfile-8 2.000 ± 0% 1.000 ± 0% -50.00% (p=0.002 n=6) geomean 39.70 28.05 -29.33% So it looks like the cost of deduplication is about 5% of overall time(including compression), which is not that bad.
1 parent 07e7716 commit 181f95a

File tree

18 files changed

+554
-318
lines changed

18 files changed

+554
-318
lines changed

.github/workflows/go.yml

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ jobs:
1212
strategy:
1313
fail-fast: false
1414
matrix:
15-
go: ['1.16', '1.17', '1.18', '1.19', '1.20', '1.21', '1.22', 'tip']
15+
go: ['1.18', '1.19', '1.20', '1.21', '1.22', 'tip']
1616
steps:
1717
- name: Checkout
1818
uses: actions/checkout@v3
@@ -21,11 +21,7 @@ jobs:
2121
uses: actions/setup-go@v4
2222
with:
2323
go-version: ${{ matrix.go }}
24-
- name: Downgrade go.mod for go 1.17 and go 1.16
25-
if: matrix.go == '1.17' || matrix.go == '1.16'
26-
run: make go/mod_16_for_testing
2724
- name: Run go/mod
28-
if: matrix.go != '1.17' && matrix.go != '1.16'
2925
run: make go/mod && git diff --exit-code
3026
- name: Install Go stable
3127
if: matrix.go == 'tip'

Makefile

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,3 @@ go/mod:
1515
cd godeltaprof/ && GO111MODULE=on go mod download
1616
cd godeltaprof/ && GO111MODULE=on go mod tidy
1717

18-
.PHONY: go/mod_16_for_testing
19-
go/mod_16_for_testing:
20-
rm -rf godeltaprof/compat/go.mod godeltaprof/compat/go.sum godeltaprof/go.mod godeltaprof/go.sum go.work otelpyroscope/
21-
cat go.mod_go16_test.txt > go.mod
22-
go mod tidy

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,4 @@ replace github.com/grafana/pyroscope-go/godeltaprof => ./godeltaprof
66

77
require github.com/grafana/pyroscope-go/godeltaprof v0.1.6
88

9-
require github.com/klauspost/compress v1.17.3 // indirect
9+
require github.com/klauspost/compress v1.17.8 // indirect

go.mod_go16_test.txt

Lines changed: 0 additions & 12 deletions
This file was deleted.

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
github.com/klauspost/compress v1.17.3 h1:qkRjuerhUU1EmXLYGkSH6EZL+vPSxIrYjLNAK4slzwA=
2-
github.com/klauspost/compress v1.17.3/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM=
1+
github.com/klauspost/compress v1.17.8 h1:YcnTYrq7MikUT7k0Yb5eceMmALQPYBW/Xltxn0NAMnU=
2+
github.com/klauspost/compress v1.17.8/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=

go.work.sum

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,12 @@ github.com/chromedp/sysutil v1.0.0 h1:+ZxhTpfpZlmchB58ih/LBHX52ky7w2VhQVKQMucy3I
66
github.com/chromedp/sysutil v1.0.0/go.mod h1:kgWmDdq8fTzXYcKIBqIYvRRTnYb9aNS9moAV0xufSww=
77
github.com/chzyer/readline v1.5.1 h1:upd/6fQk4src78LMRzh5vItIt361/o4uq553V8B5sGI=
88
github.com/chzyer/readline v1.5.1/go.mod h1:Eh+b79XXUwfKfcPLepksvw2tcLE/Ct21YObkaSkeBlk=
9-
github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0=
10-
github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
119
github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU=
1210
github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM=
1311
github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og=
1412
github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
1513
github.com/gobwas/ws v1.2.1 h1:F2aeBZrm2NDsc7vbovKrWSogd4wvfAxg0FQ89/iqOTk=
1614
github.com/gobwas/ws v1.2.1/go.mod h1:hRKAFb8wOxFROYNsT1bqfWnhX+b5MFeJM9r2ZSwg/KY=
17-
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
18-
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
19-
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
2015
github.com/ianlancetaylor/demangle v0.0.0-20230524184225-eabc099b10ab h1:BA4a7pe6ZTd9F8kXETBoijjFJ/ntaa//1wiH9BZu4zU=
2116
github.com/ianlancetaylor/demangle v0.0.0-20230524184225-eabc099b10ab/go.mod h1:gx7rwoVhcfuVKG5uya9Hs3Sxj7EIvldVofAWIUtGouw=
2217
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
@@ -27,7 +22,6 @@ github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
2722
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
2823
github.com/yuin/goldmark v1.4.13 h1:fVcFKWvrslecOb/tg+Cc05dkeYx540o0FuFt3nUVDoE=
2924
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
30-
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg=
3125
golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c=
3226
golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
3327
golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=

godeltaprof/compat/compression_test.go

Lines changed: 26 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -2,33 +2,27 @@ package compat
22

33
import (
44
"io"
5-
"math/rand"
65
"runtime"
76
"testing"
8-
9-
"github.com/grafana/pyroscope-go/godeltaprof/internal/pprof"
107
)
118

129
func BenchmarkHeapCompression(b *testing.B) {
13-
opt := &pprof.ProfileBuilderOptions{
14-
GenericsFrames: true,
15-
LazyMapping: true,
16-
}
17-
dh := new(pprof.DeltaHeapProfiler)
18-
fs := generateMemProfileRecords(512, 32, 239)
19-
rng := rand.NewSource(239)
20-
objSize := fs[0].AllocBytes / fs[0].AllocObjects
21-
nMutations := int(uint(rng.Int63())) % len(fs)
10+
h := newHeapTestHelper()
11+
fs := h.generateMemProfileRecords(512, 32)
12+
h.rng.Seed(239)
13+
nmutations := int(h.rng.Int63() % int64(len(fs)))
14+
2215
b.ResetTimer()
2316
for i := 0; i < b.N; i++ {
24-
_ = WriteHeapProto(dh, opt, io.Discard, fs, int64(runtime.MemProfileRate))
25-
for j := 0; j < nMutations; j++ {
26-
idx := int(uint(rng.Int63())) % len(fs)
27-
fs[idx].AllocObjects += 1
28-
fs[idx].AllocBytes += objSize
29-
fs[idx].FreeObjects += 1
30-
fs[idx].FreeBytes += objSize
17+
if i == 1000 {
18+
v := h.rng.Int63()
19+
if v != 7817861117094116717 {
20+
b.Errorf("unexpected random value: %d. "+
21+
"The bench should be deterministic for better comparision.", v)
22+
}
3123
}
24+
_ = WriteHeapProto(h.dp, h.opt, io.Discard, fs, int64(runtime.MemProfileRate))
25+
h.mutate(nmutations, fs)
3226
}
3327
}
3428

@@ -43,38 +37,25 @@ func BenchmarkMutexCompression(b *testing.B) {
4337
runtime.SetMutexProfileFraction(5)
4438
defer runtime.SetMutexProfileFraction(prevMutexProfileFraction)
4539

46-
opt := &pprof.ProfileBuilderOptions{
47-
GenericsFrames: true,
48-
LazyMapping: true,
49-
}
50-
dh := new(pprof.DeltaMutexProfiler)
51-
fs := generateBlockProfileRecords(512, 32, 239)
52-
rng := rand.NewSource(239)
53-
nMutations := int(uint(rng.Int63())) % len(fs)
54-
oneBlockCycles := fs[0].Cycles / fs[0].Count
40+
h := newMutexTestHelper()
41+
h.scaler = scaler
42+
fs := h.generateBlockProfileRecords(512, 32)
43+
h.rng.Seed(239)
44+
nmutations := int(h.rng.Int63() % int64(len(fs)))
5545
b.ResetTimer()
5646

5747
for i := 0; i < b.N; i++ {
58-
_ = PrintCountCycleProfile(dh, opt, io.Discard, scaler, fs)
59-
for j := 0; j < nMutations; j++ {
60-
idx := int(uint(rng.Int63())) % len(fs)
61-
fs[idx].Count += 1
62-
fs[idx].Cycles += oneBlockCycles
48+
if i == 1000 {
49+
v := h.rng.Int63()
50+
if v != 7817861117094116717 {
51+
b.Errorf("unexpected random value: %d. "+
52+
"The bench should be deterministic for better comparision.", v)
53+
}
6354
}
55+
_ = PrintCountCycleProfile(h.dp, h.opt, io.Discard, scaler, fs)
56+
h.mutate(nmutations, fs)
6457
}
6558
})
6659

6760
}
6861
}
69-
70-
func WriteHeapProto(dp *pprof.DeltaHeapProfiler, opt *pprof.ProfileBuilderOptions, w io.Writer, p []runtime.MemProfileRecord, rate int64) error {
71-
stc := pprof.HeapProfileConfig(rate)
72-
b := pprof.NewProfileBuilder(w, opt, stc)
73-
return dp.WriteHeapProto(b, p, rate)
74-
}
75-
76-
func PrintCountCycleProfile(d *pprof.DeltaMutexProfiler, opt *pprof.ProfileBuilderOptions, w io.Writer, scaler pprof.MutexProfileScaler, records []runtime.BlockProfileRecord) error {
77-
stc := pprof.MutexProfileConfig()
78-
b := pprof.NewProfileBuilder(w, opt, stc)
79-
return d.PrintCountCycleProfile(b, scaler, records)
80-
}

0 commit comments

Comments
 (0)