From 1cc33d4cc32f999a9011212469fc51c49e22dada Mon Sep 17 00:00:00 2001 From: Vincent Bernat Date: Tue, 21 Oct 2025 22:09:34 +0200 Subject: [PATCH] outlet/routing: fix lookup benchmark The lookup benchmark was incorrect. When looking up a large number of prefixes on each loop, b.Loop() calibrate on a larger and less precise value than if it were measuring only one lookup where it would iterate more to get a precise timing. The problem may also exist for the insertion benchmark, but it's difficult to do only one insertion per loop, as after many iterations, there is nothing more we can insert. I suppose BART's author is not trying to benchmark insertions because of this. See https://github.com/akvorado/akvorado/pull/2040 and https://github.com/gaissmai/bart/issues/351#issuecomment-3428806758. --- orchestrator/clickhouse/networks_test.go | 7 ++-- outlet/routing/provider/bmp/prefixes_test.go | 34 ++++++-------------- 2 files changed, 14 insertions(+), 27 deletions(-) diff --git a/orchestrator/clickhouse/networks_test.go b/orchestrator/clickhouse/networks_test.go index c0fcc9c4..7b9611ec 100644 --- a/orchestrator/clickhouse/networks_test.go +++ b/orchestrator/clickhouse/networks_test.go @@ -187,9 +187,10 @@ func BenchmarkNetworks(b *testing.B) { <-c.networksCSVReady for b.Loop() { - if err := c.networksCSVRefresh(); err != nil { - b.Fatalf("networksCSVRefresh() error:\n%+v", err) - } + err = c.networksCSVRefresh() + } + if err != nil { + b.Fatalf("networksCSVRefresh() error:\n%+v", err) } b.ReportMetric(0, "ns/op") b.ReportMetric(float64(b.Elapsed())/float64(b.N)/1_000_000, "ms/op") diff --git a/outlet/routing/provider/bmp/prefixes_test.go b/outlet/routing/provider/bmp/prefixes_test.go index 99dda85e..06d6dc31 100644 --- a/outlet/routing/provider/bmp/prefixes_test.go +++ b/outlet/routing/provider/bmp/prefixes_test.go @@ -204,18 +204,6 @@ func TestRandomRealWorldRoutes4Distribution(t *testing.T) { } } -func BenchmarkRandomRealWorldRoutes4(b *testing.B) { - prng1 := rand.New(rand.NewSource(1)) - prng2 := rand.New(rand.NewSource(2)) - for b.Loop() { - for route := range randomRealWorldRoutes4(prng1, prng2, 1000) { - _ = route - } - } - b.ReportMetric(0, "ns/op") - b.ReportMetric(float64(b.Elapsed())/float64(b.N)/1000, "ns/route") -} - func BenchmarkRIBInsertion(b *testing.B) { for _, routes := range []int{1_000, 10_000, 100_000} { for _, peers := range []int{1, 2, 5} { @@ -283,7 +271,13 @@ func BenchmarkRIBInsertion(b *testing.B) { } func BenchmarkRIBLookup(b *testing.B) { - for _, routes := range []int{1_000, 10_000, 100_000} { + for _, routes := range []int{1_000, 10_000, 100_000, 1_000_000} { + prng1 := rand.New(rand.NewSource(10)) + prng2 := rand.New(rand.NewSource(0)) + randomPrefixes := []randomRoute{} + for r := range randomRealWorldRoutes4(prng1, prng2, routes/10) { + randomPrefixes = append(randomPrefixes, r) + } for _, peers := range []int{1, 2, 5} { name := fmt.Sprintf("%d routes, %d peers", routes, peers) @@ -317,19 +311,11 @@ func BenchmarkRIBLookup(b *testing.B) { } } - prng1 = rand.New(rand.NewSource(10)) - lookups := 0 - randomPrefixes := []randomRoute{} - for r := range randomRealWorldRoutes4(prng1, prng2[0], routes/10) { - randomPrefixes = append(randomPrefixes, r) - } for b.Loop() { - for _, r := range randomPrefixes { - _, _ = rib.tree.Lookup(netip.AddrFrom16(r.Prefix.Addr().As16())) - lookups++ - } + ip4 := randomPrefixes[b.N%len(randomPrefixes)].Prefix.Addr() + _, _ = rib.tree.Lookup(ip4) } - b.ReportMetric(float64(b.Elapsed())/float64(lookups), "ns/op") + b.ReportMetric(float64(b.Elapsed())/float64(b.N), "ns/op") }) } }