From 8d7402ae212d73ac9ca4da32b336e0fc487890cd Mon Sep 17 00:00:00 2001 From: Martin Hutchinson Date: Tue, 19 May 2026 09:41:32 +0000 Subject: [PATCH 1/2] [VIndex] Added benchmark for indexing 10k entries This gives a target when switching over the MPT implementation. ``` go test -bench=BenchmarkBuild -benchmem ./vindex goos: linux goarch: amd64 pkg: github.com/transparency-dev/incubator/vindex cpu: AMD EPYC 7B12 BenchmarkBuild_InMemory-24 1 1004559670 ns/op 38192304 B/op 588597 allocs/op BenchmarkBuild_OnDisk-24 1 4810209571 ns/op 2268211632 B/op 1541229 allocs/op PASS ok github.com/transparency-dev/incubator/vindex 26.039s ``` --- vindex/map_test.go | 94 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) diff --git a/vindex/map_test.go b/vindex/map_test.go index 769f28c..0b3c11f 100644 --- a/vindex/map_test.go +++ b/vindex/map_test.go @@ -22,6 +22,7 @@ import ( "crypto/sha256" "fmt" "iter" + "math/rand" "os" "path" "sync" @@ -43,6 +44,9 @@ import ( const ( skey = "PRIVATE+KEY+logandmap+38581672+AXJ0FKWOcO2ch6WC8kP705Ed3Gxu7pVtZLhfHAQwp+FE" vkey = "logandmap+38581672+Ab/PCr1eCclRPRMBqw/r5An1xO71MCnImLiospEq6b4l" + + benchNumEntries = 10000 + benchDuplicationRatio = 0.5 ) func TestVerifiableIndex(t *testing.T) { @@ -338,3 +342,93 @@ func (s *inMemoryTreeSource) Append(leafStr string) { s.leaves = append(s.leaves, leaf) s.t.Append(rfc6962.DefaultHasher.HashLeaf(leaf)) } + +func runBenchmark(b *testing.B, opts vindex.Options) { + ctx := context.Background() + s, v, err := fnote.NewEd25519SignerVerifier(skey) + if err != nil { + b.Fatal(err) + } + + inputLog := &inMemoryTreeSource{ + t: testonly.New(rfc6962.DefaultHasher), + leaves: make([][]byte, 0), + s: s, + v: v, + } + + rng := rand.New(rand.NewSource(12345)) + + var uniqueKeys []string + for i := 0; i < benchNumEntries; i++ { + var key string + if len(uniqueKeys) > 0 && rng.Float64() < benchDuplicationRatio { + key = uniqueKeys[rng.Intn(len(uniqueKeys))] + } else { + key = fmt.Sprintf("key-%d", len(uniqueKeys)) + uniqueKeys = append(uniqueKeys, key) + } + inputLog.Append(fmt.Sprintf("%s: %d", key, i)) + } + + mapFn := func(leaf []byte) [][sha256.Size]byte { + k, _, found := bytes.Cut(leaf, []byte(":")) + if !found { + panic("colon not found") + } + return [][sha256.Size]byte{sha256.Sum256(k)} + } + + b.ResetTimer() + b.ReportAllocs() + + for i := 0; i < b.N; i++ { + b.StopTimer() + dir, err := os.MkdirTemp("", "vindex-bench") + if err != nil { + b.Fatal(err) + } + + iterCtx, iterCancel := context.WithCancel(ctx) + + outputLog, closer, err := vindex.NewOutputLog(iterCtx, path.Join(dir, "outputlog"), s, v, vindex.OutputLogOpts{}) + if err != nil { + iterCancel() + os.RemoveAll(dir) + b.Fatal(err) + } + + vi, err := vindex.NewVerifiableIndex(iterCtx, inputLog, mapFn, outputLog, dir, opts) + if err != nil { + closer() + iterCancel() + os.RemoveAll(dir) + b.Fatal(err) + } + + b.StartTimer() + if err := vi.Update(iterCtx); err != nil { + iterCancel() + b.Fatal(err) + } + b.StopTimer() + + if err := vi.Close(); err != nil { + iterCancel() + b.Fatal(err) + } + iterCancel() + closer() + if err := os.RemoveAll(dir); err != nil { + b.Fatal(err) + } + } +} + +func BenchmarkBuild_InMemory(b *testing.B) { + runBenchmark(b, vindex.Options{PersistIndex: false}) +} + +func BenchmarkBuild_OnDisk(b *testing.B) { + runBenchmark(b, vindex.Options{PersistIndex: true}) +} From 7cd46453805cb7c88010c7d3e72151d53e3257ee Mon Sep 17 00:00:00 2001 From: Martin Hutchinson Date: Tue, 19 May 2026 10:38:14 +0000 Subject: [PATCH 2/2] Review comments --- vindex/map_test.go | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/vindex/map_test.go b/vindex/map_test.go index 0b3c11f..1e89164 100644 --- a/vindex/map_test.go +++ b/vindex/map_test.go @@ -360,7 +360,7 @@ func runBenchmark(b *testing.B, opts vindex.Options) { rng := rand.New(rand.NewSource(12345)) var uniqueKeys []string - for i := 0; i < benchNumEntries; i++ { + for i := range benchNumEntries { var key string if len(uniqueKeys) > 0 && rng.Float64() < benchDuplicationRatio { key = uniqueKeys[rng.Intn(len(uniqueKeys))] @@ -382,7 +382,7 @@ func runBenchmark(b *testing.B, opts vindex.Options) { b.ResetTimer() b.ReportAllocs() - for i := 0; i < b.N; i++ { + for b.Loop() { b.StopTimer() dir, err := os.MkdirTemp("", "vindex-bench") if err != nil { @@ -392,34 +392,27 @@ func runBenchmark(b *testing.B, opts vindex.Options) { iterCtx, iterCancel := context.WithCancel(ctx) outputLog, closer, err := vindex.NewOutputLog(iterCtx, path.Join(dir, "outputlog"), s, v, vindex.OutputLogOpts{}) - if err != nil { + b.Cleanup(func() { iterCancel() - os.RemoveAll(dir) + _ = os.RemoveAll(dir) + if closer != nil { + closer() + } + }) + if err != nil { b.Fatal(err) } vi, err := vindex.NewVerifiableIndex(iterCtx, inputLog, mapFn, outputLog, dir, opts) if err != nil { - closer() - iterCancel() - os.RemoveAll(dir) b.Fatal(err) } b.StartTimer() if err := vi.Update(iterCtx); err != nil { - iterCancel() b.Fatal(err) } - b.StopTimer() - if err := vi.Close(); err != nil { - iterCancel() - b.Fatal(err) - } - iterCancel() - closer() - if err := os.RemoveAll(dir); err != nil { b.Fatal(err) } }