From 0f0c4ef39683fdc7358c0b98052b71e1dbc20503 Mon Sep 17 00:00:00 2001 From: Daniil Porokhnin Date: Thu, 20 Nov 2025 14:39:53 +0300 Subject: [PATCH 1/5] chore: skip candidates for deletion --- cache/cache_test.go | 2 ++ frac/active_ids_test.go | 4 ++++ node/bench_test.go | 4 ++++ pattern/pattern_test.go | 4 ++++ tests/setup/doc_test.go | 8 ++++++++ 5 files changed, 22 insertions(+) diff --git a/cache/cache_test.go b/cache/cache_test.go index 8ef40be9..52979647 100644 --- a/cache/cache_test.go +++ b/cache/cache_test.go @@ -129,6 +129,8 @@ func TestStress(t *testing.T) { } func BenchmarkBucketClean(b *testing.B) { + b.SkipNow() + b.StopTimer() cleaner := NewCleaner(0, nil) diff --git a/frac/active_ids_test.go b/frac/active_ids_test.go index ae2f6111..a07a4cfe 100644 --- a/frac/active_ids_test.go +++ b/frac/active_ids_test.go @@ -33,6 +33,8 @@ func TestSeqListAppend(t *testing.T) { } func BenchmarkMutexListAppend(b *testing.B) { + b.SkipNow() + gr := 2 mu := sync.Mutex{} b.SetBytes(int64(gr * 8000000)) @@ -57,6 +59,8 @@ func BenchmarkMutexListAppend(b *testing.B) { } func BenchmarkSeqListAppend(b *testing.B) { + b.SkipNow() + gr := 2 b.SetBytes(int64(gr * 8000000)) for n := 0; n < b.N; n++ { diff --git a/node/bench_test.go b/node/bench_test.go index d16e50e6..a5570805 100644 --- a/node/bench_test.go +++ b/node/bench_test.go @@ -25,6 +25,8 @@ func Generate(n int) ([]uint32, uint32) { // bench for base point // you can't go faster func BenchmarkCopy(b *testing.B) { + b.SkipNow() + res := make([]uint32, b.N) n := newNodeStaticSize(b.N) b.ResetTimer() @@ -33,6 +35,8 @@ func BenchmarkCopy(b *testing.B) { // base point func BenchmarkIterate(b *testing.B) { + b.SkipNow() + res := make([]uint32, b.N) n := newNodeStaticSize(b.N) b.ResetTimer() diff --git a/pattern/pattern_test.go b/pattern/pattern_test.go index 2c9a5702..2597c7dc 100644 --- a/pattern/pattern_test.go +++ b/pattern/pattern_test.go @@ -515,6 +515,8 @@ func TestFindSequence(t *testing.T) { } func BenchmarkFindSequence_Deterministic(b *testing.B) { + b.SkipNow() + type testCase struct { haystack []byte needles [][]byte @@ -556,6 +558,8 @@ func BenchmarkFindSequence_Deterministic(b *testing.B) { } func BenchmarkFindSequence_Random(b *testing.B) { + b.SkipNow() + sizes := []struct { name string haystackSize int diff --git a/tests/setup/doc_test.go b/tests/setup/doc_test.go index bf463de1..8c24e434 100644 --- a/tests/setup/doc_test.go +++ b/tests/setup/doc_test.go @@ -67,6 +67,8 @@ func BenchmarkRandomJSON(b *testing.B) { } func BenchmarkRandomDoc(b *testing.B) { + b.SkipNow() + RunParallel(4, func() { sum := 0 for i := 0; i < b.N; i++ { @@ -79,6 +81,8 @@ func BenchmarkRandomDoc(b *testing.B) { } func BenchmarkGenerateDocs(b *testing.B) { + b.SkipNow() + res := GenerateDocs(b.N, func(_ int, doc *ExampleDoc) { *doc = *RandomDoc(1) }) @@ -86,11 +90,15 @@ func BenchmarkGenerateDocs(b *testing.B) { } func BenchmarkGenerateDocsJSON(b *testing.B) { + b.SkipNow() + res := GenerateDocsJSON(b.N, false) _ = res } func BenchmarkGenerateDocsJSONFields(b *testing.B) { + b.SkipNow() + res := GenerateDocsJSON(b.N, true) _ = res } From f6329cdba2fd81fc9bf5f9c18b08e3a621b05b4e Mon Sep 17 00:00:00 2001 From: Daniil Porokhnin Date: Thu, 20 Nov 2025 14:40:29 +0300 Subject: [PATCH 2/5] ci: increase `-count` to 5 on `pull_request` --- .github/workflows/continuous-benchmarks.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/continuous-benchmarks.yml b/.github/workflows/continuous-benchmarks.yml index f40c5e66..78e3a768 100644 --- a/.github/workflows/continuous-benchmarks.yml +++ b/.github/workflows/continuous-benchmarks.yml @@ -28,7 +28,7 @@ jobs: - name: Run Golang benchmarks shell: bash run: | - COUNT=$([[ "${{ github.event_name }}" == "pull_request" ]] && echo 1 || echo 5) + COUNT=$([[ "${{ github.event_name }}" == "pull_request" ]] && echo 5 || echo 5) LOG_LEVEL=FATAL GOMAXPROCS=4 go test -run='$^' -count=$COUNT -bench=. -benchmem ./... | tee ${{ runner.temp }}/gotool.txt # Add GitHub job summary for pull requests. From 832f6717be74fb86baf524c59cf08d54c1948798 Mon Sep 17 00:00:00 2001 From: Daniil Porokhnin Date: Thu, 20 Nov 2025 16:07:12 +0300 Subject: [PATCH 3/5] chore: skip one more benchmark --- tests/setup/doc_test.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/setup/doc_test.go b/tests/setup/doc_test.go index 8c24e434..4107921a 100644 --- a/tests/setup/doc_test.go +++ b/tests/setup/doc_test.go @@ -55,6 +55,8 @@ func RunParallel(n int, f func()) { } func BenchmarkRandomJSON(b *testing.B) { + b.SkipNow() + RunParallel(4, func() { sum := 0 for i := 0; i < b.N; i++ { From 50512afb699c7dd2d2eb4c2b4387744f46f380b0 Mon Sep 17 00:00:00 2001 From: Daniil Porokhnin Date: Thu, 20 Nov 2025 17:44:36 +0300 Subject: [PATCH 4/5] chore: fix benchmarks in `node` package --- node/bench_test.go | 209 +++++++++++++++++++++++++++++---------------- node/node_test.go | 19 +++-- 2 files changed, 148 insertions(+), 80 deletions(-) diff --git a/node/bench_test.go b/node/bench_test.go index a5570805..5ad53664 100644 --- a/node/bench_test.go +++ b/node/bench_test.go @@ -1,23 +1,24 @@ package node import ( - "math/rand" + "fmt" "testing" - - "github.com/stretchr/testify/assert" + "time" ) -func newNodeStaticSize(size int) *staticAsc { - data, _ := Generate(size) - return &staticAsc{staticCursor: staticCursor{data: data}} -} +var ( + // Setup dataset size and data itself. + lidsCount uint32 = 100_000 + // lids is a sorted slice [1; 1 + lidsCount); + lids, last = generate(lidsCount) +) -func Generate(n int) ([]uint32, uint32) { +func generate(n uint32) ([]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 += 1 } return v, last } @@ -28,7 +29,7 @@ func BenchmarkCopy(b *testing.B) { b.SkipNow() res := make([]uint32, b.N) - n := newNodeStaticSize(b.N) + var n *staticAsc = nil b.ResetTimer() copy(res, n.data) } @@ -38,7 +39,7 @@ func BenchmarkIterate(b *testing.B) { b.SkipNow() res := make([]uint32, b.N) - n := newNodeStaticSize(b.N) + var n *staticAsc = nil b.ResetTimer() for i, v := range n.data { res[i] = v @@ -46,90 +47,152 @@ func BenchmarkIterate(b *testing.B) { } func BenchmarkStatic(b *testing.B) { - res := make([]uint32, 0, b.N) - n := newNodeStaticSize(b.N) - b.ResetTimer() - res = readAllInto(n, res) - assert.Equal(b, cap(res), b.N) + b.Run("asc", func(b *testing.B) { + for b.Loop() { + b.StopTimer() + n := NewStatic(lids, false) + b.StartTimer() + + all(n) + } + }) + + b.Run("desc", func(b *testing.B) { + for b.Loop() { + b.StopTimer() + n := NewStatic(lids, true) + b.StartTimer() + + all(n) + } + }) } func BenchmarkNot(b *testing.B) { - v, last := Generate(b.N) - res := make([]uint32, 0, last+1) - n := NewNot(NewStatic(v, false), 1, last, false) - b.ResetTimer() - res = readAllInto(n, res) - assert.Equal(b, cap(res), int(last)+1) + for b.Loop() { + b.StopTimer() + n := NewNot( + NewStatic(lids, false), + 1, last, false, + ) + b.StartTimer() + + all(n) + } } func BenchmarkNotEmpty(b *testing.B) { - res := make([]uint32, 0, b.N*2) - n := NewNot(NewStatic(nil, false), 1, uint32(b.N), false) - b.ResetTimer() - res = readAllInto(n, res) - assert.Equal(b, cap(res), b.N*2) + for b.Loop() { + b.StopTimer() + n := NewNot( + NewStatic(nil, false), + 1, uint32(lidsCount), false, + ) + b.StartTimer() + + all(n) + } } func BenchmarkOr(b *testing.B) { - res := make([]uint32, 0, b.N*2) - n := NewOr(newNodeStaticSize(b.N), newNodeStaticSize(b.N), false) - b.ResetTimer() - res = readAllInto(n, res) - assert.Equal(b, cap(res), b.N*2) + for b.Loop() { + b.StopTimer() + n := NewOr( + NewStatic(lids, false), + NewStatic(lids, false), + false, + ) + b.StartTimer() + + all(n) + } } func BenchmarkAnd(b *testing.B) { - res := make([]uint32, 0, b.N) - n := NewAnd(newNodeStaticSize(b.N), newNodeStaticSize(b.N), false) - b.ResetTimer() - res = readAllInto(n, res) - assert.Equal(b, cap(res), b.N) + for b.Loop() { + b.StopTimer() + n := NewAnd( + NewStatic(lids, false), + NewStatic(lids, false), + false, + ) + b.StartTimer() + + all(n) + } } func BenchmarkNAnd(b *testing.B) { - res := make([]uint32, 0, b.N) - n := NewNAnd(newNodeStaticSize(b.N), newNodeStaticSize(b.N), false) - b.ResetTimer() - res = readAllInto(n, res) - assert.Equal(b, cap(res), b.N) + for b.Loop() { + b.StopTimer() + n := NewNAnd( + NewStatic(lids, false), + NewStatic(lids, false), + false, + ) + b.StartTimer() + + all(n) + } } func BenchmarkAndTree(b *testing.B) { - n1 := NewAnd(newNodeStaticSize(b.N), newNodeStaticSize(b.N), false) - n2 := NewAnd(newNodeStaticSize(b.N), newNodeStaticSize(b.N), false) - n3 := NewAnd(newNodeStaticSize(b.N), newNodeStaticSize(b.N), false) - n4 := NewAnd(newNodeStaticSize(b.N), newNodeStaticSize(b.N), false) - n12 := NewAnd(n1, n2, false) - n34 := NewAnd(n3, n4, false) - n := NewAnd(n12, n34, false) - res := make([]uint32, 0, b.N) - b.ResetTimer() - res = readAllInto(n, res) - assert.Equal(b, cap(res), b.N) + for b.Loop() { + b.StopTimer() + + n1 := NewAnd(NewStatic(lids, false), NewStatic(lids, false), false) + n2 := NewAnd(NewStatic(lids, false), NewStatic(lids, false), false) + n3 := NewAnd(NewStatic(lids, false), NewStatic(lids, false), false) + n4 := NewAnd(NewStatic(lids, false), NewStatic(lids, false), false) + + n12 := NewAnd(n1, n2, false) + n34 := NewAnd(n3, n4, false) + + n := NewAnd(n12, n34, false) + b.StartTimer() + + all(n) + } } func BenchmarkOrTree(b *testing.B) { - n1 := NewOr(newNodeStaticSize(b.N), newNodeStaticSize(b.N), false) - n2 := NewOr(newNodeStaticSize(b.N), newNodeStaticSize(b.N), false) - n3 := NewOr(newNodeStaticSize(b.N), newNodeStaticSize(b.N), false) - n4 := NewOr(newNodeStaticSize(b.N), newNodeStaticSize(b.N), false) - n12 := NewOr(n1, n2, false) - n34 := NewOr(n3, n4, false) - n := NewOr(n12, n34, false) - res := make([]uint32, 0, b.N*8) - b.ResetTimer() - res = readAllInto(n, res) - assert.Equal(b, cap(res), b.N*8) + for b.Loop() { + b.StopTimer() + + n1 := NewOr(NewStatic(lids, false), NewStatic(lids, false), false) + n2 := NewOr(NewStatic(lids, false), NewStatic(lids, false), false) + n3 := NewOr(NewStatic(lids, false), NewStatic(lids, false), false) + n4 := NewOr(NewStatic(lids, false), NewStatic(lids, false), false) + + n12 := NewOr(n1, n2, false) + n34 := NewOr(n3, n4, false) + + n := NewOr(n12, n34, false) + b.StartTimer() + + all(n) + } } +// FIXME(dkharms): What is wrong here? +// One iteration finishes in 20ns - that's impossible. func BenchmarkComplex(b *testing.B) { - res := make([]uint32, 0, b.N*2) - n1 := NewAnd(newNodeStaticSize(b.N), newNodeStaticSize(b.N), false) - n2 := NewOr(newNodeStaticSize(b.N), newNodeStaticSize(b.N), false) - n3 := NewNAnd(newNodeStaticSize(b.N), newNodeStaticSize(b.N), false) - n12 := NewOr(n1, n2, false) - n := NewAnd(n12, n3, false) - b.ResetTimer() - res = readAllInto(n, res) - assert.Equal(b, cap(res), b.N*2) + b.SkipNow() + + for b.Loop() { + b.StopTimer() + + n1 := NewAnd(NewStatic(lids, false), NewStatic(lids, false), false) + n2 := NewOr(NewStatic(lids, false), NewStatic(lids, false), false) + n3 := NewNAnd(NewStatic(lids, false), NewStatic(lids, false), false) + + n12 := NewOr(n1, n2, false) + + n := NewAnd(n12, n3, false) + b.StartTimer() + + start := time.Now() + all(n) + fmt.Printf("time.Since(start): %v\n", time.Since(start)) + } } diff --git a/node/node_test.go b/node/node_test.go index 6da2d8a1..4eb3f399 100644 --- a/node/node_test.go +++ b/node/node_test.go @@ -7,17 +7,22 @@ import ( "github.com/stretchr/testify/require" ) -func readAllInto(node Node, ids []uint32) []uint32 { - id, has := node.Next() +func all(node Node) { + _, has := node.Next() for has { - ids = append(ids, id) - id, has = node.Next() + _, has = node.Next() } - return ids } -func readAll(node Node) []uint32 { - return readAllInto(node, nil) +func readAll(node Node) (lids []uint32) { + v, has := node.Next() + + for has { + lids = append(lids, v) + v, has = node.Next() + } + + return lids } func getRemainingSlice(t *testing.T, node Node) []uint32 { From 35d1aa319d96a4dfe6dace6ebfc23ac627c061a3 Mon Sep 17 00:00:00 2001 From: Daniil Porokhnin Date: Thu, 20 Nov 2025 17:44:52 +0300 Subject: [PATCH 5/5] chore: use `b.Loop` in time parsing benchmarks --- indexer/processor_test.go | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/indexer/processor_test.go b/indexer/processor_test.go index 0b25c5f3..485153d5 100644 --- a/indexer/processor_test.go +++ b/indexer/processor_test.go @@ -89,29 +89,20 @@ func BenchmarkParseESTime(b *testing.B) { const toParseRFC3339 = "2024-04-19T18:04:25.999Z" b.Run("es_stdlib", func(b *testing.B) { - for i := 0; i < b.N; i++ { - _, err := time.Parse(consts.ESTimeFormat, toParse) - if err != nil { - b.Fatal(err) - } + for b.Loop() { + time.Parse(consts.ESTimeFormat, toParse) } }) b.Run("handwritten", func(b *testing.B) { - for i := 0; i < b.N; i++ { - _, ok := parseESTime(toParse) - if !ok { - b.Fatal() - } + for b.Loop() { + parseESTime(toParse) } }) b.Run("rfc3339", func(b *testing.B) { - for i := 0; i < b.N; i++ { - _, err := time.Parse(time.RFC3339, toParseRFC3339) - if err != nil { - b.Fatal(err) - } + for b.Loop() { + time.Parse(time.RFC3339, toParseRFC3339) } }) }