From eec303fc5beb986e5815868fbf71be11c8b5e09c Mon Sep 17 00:00:00 2001 From: Andrei Cheboksarov <37665782+cheb0@users.noreply.github.com> Date: Fri, 6 Mar 2026 14:35:03 +0300 Subject: [PATCH 1/3] make Node benches more stable --- frac/processor/aggregator_test.go | 20 +++++++---- node/bench_test.go | 55 ++++++++++++++++++++----------- 2 files changed, 49 insertions(+), 26 deletions(-) diff --git a/frac/processor/aggregator_test.go b/frac/processor/aggregator_test.go index d5f12351..23eb53a5 100644 --- a/frac/processor/aggregator_test.go +++ b/frac/processor/aggregator_test.go @@ -79,12 +79,14 @@ func TestSingleSourceCountAggregatorWithInterval(t *testing.T) { assert.Equal(t, int64(1), agg.notExists) } -func Generate(n int) ([]uint32, uint32) { +const benchRandSeed int64 = 1 + +func Generate(r *rand.Rand, n int) ([]uint32, uint32) { v := make([]uint32, n) last := uint32(1) for i := range v { v[i] = last - last += uint32(1 + rand.Intn(5)) + last += uint32(1 + r.Intn(5)) } return v, last } @@ -94,12 +96,14 @@ func BenchmarkAggDeep(b *testing.B) { for _, s := range sizes { b.Run(fmt.Sprintf("size=%d", s), func(b *testing.B) { - v, _ := Generate(s) + r := rand.New(rand.NewSource(benchRandSeed)) + v, _ := Generate(r, s) src := node.NewSourcedNodeWrapper(node.NewStatic(v, false), 0) iter := NewSourcedNodeIterator(src, nil, make([]uint32, 1), iteratorLimit{limit: 0, err: consts.ErrTooManyGroupTokens}, false) n := NewSingleSourceCountAggregator(iter, provideExtractTimeFunc(nil, nil, 0)) - vals, _ := Generate(s) + vals, _ := Generate(r, s) + b.ResetTimer() for b.Loop() { for _, v := range vals { if err := n.Next(v); err != nil { @@ -116,13 +120,14 @@ func BenchmarkAggWide(b *testing.B) { for _, s := range sizes { b.Run(fmt.Sprintf("size=%d", s), func(b *testing.B) { - v, _ := Generate(s) + r := rand.New(rand.NewSource(benchRandSeed)) + v, _ := Generate(r, s) factor := int(math.Sqrt(float64(s))) wide := make([][]uint32, s/factor) for i := range wide { for range factor { - wide[i] = append(wide[i], v[rand.Intn(s)]) + wide[i] = append(wide[i], v[r.Intn(s)]) } slices.Sort(wide[i]) } @@ -131,8 +136,9 @@ func BenchmarkAggWide(b *testing.B) { iter := NewSourcedNodeIterator(source, nil, make([]uint32, len(wide)), iteratorLimit{limit: 0, err: consts.ErrTooManyGroupTokens}, false) n := NewSingleSourceCountAggregator(iter, provideExtractTimeFunc(nil, nil, 0)) - vals, _ := Generate(s) + vals, _ := Generate(r, s) + b.ResetTimer() for b.Loop() { for _, v := range vals { if err := n.Next(v); err != nil { diff --git a/node/bench_test.go b/node/bench_test.go index 6f2c5b7c..1ed4bf22 100644 --- a/node/bench_test.go +++ b/node/bench_test.go @@ -8,17 +8,19 @@ import ( "github.com/stretchr/testify/assert" ) -func newNodeStaticSize(size int) *staticAsc { - data, _ := Generate(size) +const benchRandSeed int64 = 1 + +func newNodeStaticSize(r *rand.Rand, size int) *staticAsc { + data, _ := Generate(r, size) return &staticAsc{staticCursor: staticCursor{data: data}} } -func Generate(n int) ([]uint32, uint32) { +func Generate(r *rand.Rand, n int) ([]uint32, uint32) { v := make([]uint32, n) last := uint32(1) for i := 0; i < len(v); i++ { v[i] = last - last += uint32(1 + rand.Intn(5)) + last += uint32(1 + r.Intn(5)) } return v, last } @@ -28,10 +30,12 @@ func BenchmarkNot(b *testing.B) { for _, s := range sizes { b.Run(fmt.Sprintf("size=%d", s), func(b *testing.B) { - v, last := Generate(s) + r := rand.New(rand.NewSource(benchRandSeed)) + v, last := Generate(r, s) res := make([]uint32, 0, last+1) n := NewNot(NewStatic(v, false), 1, last, false) + b.ResetTimer() for b.Loop() { res = readAllInto(n, res) } @@ -49,6 +53,7 @@ func BenchmarkNotEmpty(b *testing.B) { res := make([]uint32, 0, s*2) n := NewNot(NewStatic(nil, false), 1, uint32(s), false) + b.ResetTimer() for b.Loop() { res = readAllInto(n, res) } @@ -64,9 +69,11 @@ func BenchmarkOr(b *testing.B) { for _, s := range sizes { b.Run(fmt.Sprintf("size=%d", s), func(b *testing.B) { + r := rand.New(rand.NewSource(benchRandSeed)) res := make([]uint32, 0, s*2) - n := NewOr(newNodeStaticSize(s), newNodeStaticSize(s), false) + n := NewOr(newNodeStaticSize(r, s), newNodeStaticSize(r, s), false) + b.ResetTimer() for b.Loop() { res = readAllInto(n, res) } @@ -81,9 +88,11 @@ func BenchmarkAnd(b *testing.B) { for _, s := range sizes { b.Run(fmt.Sprintf("size=%d", s), func(b *testing.B) { + r := rand.New(rand.NewSource(benchRandSeed)) res := make([]uint32, 0, s) - n := NewAnd(newNodeStaticSize(s), newNodeStaticSize(s), false) + n := NewAnd(newNodeStaticSize(r, s), newNodeStaticSize(r, s), false) + b.ResetTimer() for b.Loop() { res = readAllInto(n, res) } @@ -98,9 +107,11 @@ func BenchmarkNAnd(b *testing.B) { for _, s := range sizes { b.Run(fmt.Sprintf("size=%d", s), func(b *testing.B) { + r := rand.New(rand.NewSource(benchRandSeed)) res := make([]uint32, 0, s) - n := NewNAnd(newNodeStaticSize(s), newNodeStaticSize(s), false) + n := NewNAnd(newNodeStaticSize(r, s), newNodeStaticSize(r, s), false) + b.ResetTimer() for b.Loop() { res = readAllInto(n, res) } @@ -115,15 +126,17 @@ func BenchmarkAndTree(b *testing.B) { for _, s := range sizes { b.Run(fmt.Sprintf("size=%d", s), func(b *testing.B) { - n1 := NewAnd(newNodeStaticSize(s), newNodeStaticSize(s), false) - n2 := NewAnd(newNodeStaticSize(s), newNodeStaticSize(s), false) - n3 := NewAnd(newNodeStaticSize(s), newNodeStaticSize(s), false) - n4 := NewAnd(newNodeStaticSize(s), newNodeStaticSize(s), false) + r := rand.New(rand.NewSource(benchRandSeed)) + n1 := NewAnd(newNodeStaticSize(r, s), newNodeStaticSize(r, s), false) + n2 := NewAnd(newNodeStaticSize(r, s), newNodeStaticSize(r, s), false) + n3 := NewAnd(newNodeStaticSize(r, s), newNodeStaticSize(r, s), false) + n4 := NewAnd(newNodeStaticSize(r, s), newNodeStaticSize(r, s), false) n12 := NewAnd(n1, n2, false) n34 := NewAnd(n3, n4, false) n := NewAnd(n12, n34, false) res := make([]uint32, 0, s) + b.ResetTimer() for b.Loop() { res = readAllInto(n, res) } @@ -138,15 +151,17 @@ func BenchmarkOrTree(b *testing.B) { for _, s := range sizes { b.Run(fmt.Sprintf("size=%d", s), func(b *testing.B) { - n1 := NewOr(newNodeStaticSize(s), newNodeStaticSize(s), false) - n2 := NewOr(newNodeStaticSize(s), newNodeStaticSize(s), false) - n3 := NewOr(newNodeStaticSize(s), newNodeStaticSize(s), false) - n4 := NewOr(newNodeStaticSize(s), newNodeStaticSize(s), false) + r := rand.New(rand.NewSource(benchRandSeed)) + n1 := NewOr(newNodeStaticSize(r, s), newNodeStaticSize(r, s), false) + n2 := NewOr(newNodeStaticSize(r, s), newNodeStaticSize(r, s), false) + n3 := NewOr(newNodeStaticSize(r, s), newNodeStaticSize(r, s), false) + n4 := NewOr(newNodeStaticSize(r, s), newNodeStaticSize(r, s), false) n12 := NewOr(n1, n2, false) n34 := NewOr(n3, n4, false) n := NewOr(n12, n34, false) res := make([]uint32, 0, s*8) + b.ResetTimer() for b.Loop() { res = readAllInto(n, res) } @@ -162,13 +177,15 @@ func BenchmarkComplex(b *testing.B) { for _, s := range sizes { b.Run(fmt.Sprintf("size=%d", s), func(b *testing.B) { + r := rand.New(rand.NewSource(benchRandSeed)) res := make([]uint32, 0, s*2) - n1 := NewAnd(newNodeStaticSize(s), newNodeStaticSize(s), false) - n2 := NewOr(newNodeStaticSize(s), newNodeStaticSize(s), false) - n3 := NewNAnd(newNodeStaticSize(s), newNodeStaticSize(s), false) + n1 := NewAnd(newNodeStaticSize(r, s), newNodeStaticSize(r, s), false) + n2 := NewOr(newNodeStaticSize(r, s), newNodeStaticSize(r, s), false) + n3 := NewNAnd(newNodeStaticSize(r, s), newNodeStaticSize(r, s), false) n12 := NewOr(n1, n2, false) n := NewAnd(n12, n3, false) + b.ResetTimer() for b.Loop() { res = readAllInto(n, res) } From e0b2a32e2d8f07519e2770cebb7189b41f37c1e0 Mon Sep 17 00:00:00 2001 From: Andrei Cheboksarov <37665782+cheb0@users.noreply.github.com> Date: Wed, 11 Mar 2026 13:46:20 +0300 Subject: [PATCH 2/3] b.ResetTimer() is not needed when using b.Loop() --- frac/processor/aggregator_test.go | 2 -- node/bench_test.go | 6 ------ 2 files changed, 8 deletions(-) diff --git a/frac/processor/aggregator_test.go b/frac/processor/aggregator_test.go index 23eb53a5..2c62011d 100644 --- a/frac/processor/aggregator_test.go +++ b/frac/processor/aggregator_test.go @@ -103,7 +103,6 @@ func BenchmarkAggDeep(b *testing.B) { n := NewSingleSourceCountAggregator(iter, provideExtractTimeFunc(nil, nil, 0)) vals, _ := Generate(r, s) - b.ResetTimer() for b.Loop() { for _, v := range vals { if err := n.Next(v); err != nil { @@ -138,7 +137,6 @@ func BenchmarkAggWide(b *testing.B) { n := NewSingleSourceCountAggregator(iter, provideExtractTimeFunc(nil, nil, 0)) vals, _ := Generate(r, s) - b.ResetTimer() for b.Loop() { for _, v := range vals { if err := n.Next(v); err != nil { diff --git a/node/bench_test.go b/node/bench_test.go index 1ed4bf22..35f40c26 100644 --- a/node/bench_test.go +++ b/node/bench_test.go @@ -35,7 +35,6 @@ func BenchmarkNot(b *testing.B) { res := make([]uint32, 0, last+1) n := NewNot(NewStatic(v, false), 1, last, false) - b.ResetTimer() for b.Loop() { res = readAllInto(n, res) } @@ -53,7 +52,6 @@ func BenchmarkNotEmpty(b *testing.B) { res := make([]uint32, 0, s*2) n := NewNot(NewStatic(nil, false), 1, uint32(s), false) - b.ResetTimer() for b.Loop() { res = readAllInto(n, res) } @@ -92,7 +90,6 @@ func BenchmarkAnd(b *testing.B) { res := make([]uint32, 0, s) n := NewAnd(newNodeStaticSize(r, s), newNodeStaticSize(r, s), false) - b.ResetTimer() for b.Loop() { res = readAllInto(n, res) } @@ -111,7 +108,6 @@ func BenchmarkNAnd(b *testing.B) { res := make([]uint32, 0, s) n := NewNAnd(newNodeStaticSize(r, s), newNodeStaticSize(r, s), false) - b.ResetTimer() for b.Loop() { res = readAllInto(n, res) } @@ -161,7 +157,6 @@ func BenchmarkOrTree(b *testing.B) { n := NewOr(n12, n34, false) res := make([]uint32, 0, s*8) - b.ResetTimer() for b.Loop() { res = readAllInto(n, res) } @@ -185,7 +180,6 @@ func BenchmarkComplex(b *testing.B) { n12 := NewOr(n1, n2, false) n := NewAnd(n12, n3, false) - b.ResetTimer() for b.Loop() { res = readAllInto(n, res) } From cd0e94108e9dc9b68fbc40fda40c6e12e07649c6 Mon Sep 17 00:00:00 2001 From: Andrei Cheboksarov <37665782+cheb0@users.noreply.github.com> Date: Tue, 17 Mar 2026 10:06:20 +0400 Subject: [PATCH 3/3] review: remove ResetTimer --- node/bench_test.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/node/bench_test.go b/node/bench_test.go index 35f40c26..81872217 100644 --- a/node/bench_test.go +++ b/node/bench_test.go @@ -71,7 +71,6 @@ func BenchmarkOr(b *testing.B) { res := make([]uint32, 0, s*2) n := NewOr(newNodeStaticSize(r, s), newNodeStaticSize(r, s), false) - b.ResetTimer() for b.Loop() { res = readAllInto(n, res) } @@ -132,7 +131,6 @@ func BenchmarkAndTree(b *testing.B) { n := NewAnd(n12, n34, false) res := make([]uint32, 0, s) - b.ResetTimer() for b.Loop() { res = readAllInto(n, res) }