Skip to content

Commit

Permalink
labels/cidr: Add benchmark for concurrent exection of GetCIDRLabels
Browse files Browse the repository at this point in the history
Adding a LRU cache to memoize GetCIDRLabels means sharing state between
different goroutines concurrently executing GetCIDRLabels.

To measure the scalability of the LRU cache + mutex approach against the
non-cached previous version, a benchmark with increasing number of
goroutines is added.

Running the benchmark for the current version and the previous one shows
that the memoization gives a performance improvement even when up to 48
goroutines compete for the exclusive access to the LRU cache:

name                          old time/op  new time/op  delta
GetCIDRLabelsConcurrent/1-8    493µs ±31%   259µs ± 4%  -47.54%  (p=0.000 n=20+9)
GetCIDRLabelsConcurrent/2-8    889µs ±10%   474µs ± 5%  -46.69%  (p=0.000 n=19+10)
GetCIDRLabelsConcurrent/4-8   1.74ms ± 3%  0.89ms ± 4%  -49.04%  (p=0.000 n=20+10)
GetCIDRLabelsConcurrent/16-8  7.14ms ± 6%  3.77ms ± 8%  -47.20%  (p=0.000 n=18+10)
GetCIDRLabelsConcurrent/32-8  14.3ms ± 6%   7.3ms ± 2%  -48.69%  (p=0.000 n=20+9)
GetCIDRLabelsConcurrent/48-8  21.9ms ± 5%  11.1ms ± 3%  -49.24%  (p=0.000 n=19+10)

Signed-off-by: Fabio Falzoi <fabio.falzoi@isovalent.com>
  • Loading branch information
pippolo84 committed Oct 14, 2023
1 parent 15067f5 commit a424d09
Showing 1 changed file with 40 additions and 0 deletions.
40 changes: 40 additions & 0 deletions pkg/labels/cidr/cidr_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@
package cidr

import (
"math/rand"
"net/netip"
"runtime"
"strconv"
"sync"
"testing"

. "github.com/cilium/checkmate"
Expand Down Expand Up @@ -318,6 +321,43 @@ func BenchmarkLabels_SortedListCIDRIDs(b *testing.B) {
}
}

func BenchmarkGetCIDRLabelsConcurrent(b *testing.B) {
prefixes := make([]netip.Prefix, 0, 16)
octets := [4]byte{0, 0, 1, 1}
for i := 0; i < 16; i++ {
octets[0], octets[1] = byte(rand.Intn(256)), byte(rand.Intn(256))
prefixes = append(prefixes, netip.PrefixFrom(netip.AddrFrom4(octets), 32))
}

for _, goroutines := range []int{1, 2, 4, 16, 32, 48} {
b.Run(strconv.Itoa(goroutines), func(b *testing.B) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
b.StopTimer()
start := make(chan struct{})
var wg sync.WaitGroup

wg.Add(goroutines)
for j := 0; j < goroutines; j++ {
go func() {
defer wg.Done()

<-start

for k := 0; k < 64; k++ {
_ = GetCIDRLabels(prefixes[rand.Intn(len(prefixes))])
}
}()
}

b.StartTimer()
close(start)
wg.Wait()
}
})
}
}

// BenchmarkCIDRLabelsCacheHeapUsageIPv4 should be run with -benchtime=1x
func BenchmarkCIDRLabelsCacheHeapUsageIPv4(b *testing.B) {
b.Skip()
Expand Down

0 comments on commit a424d09

Please sign in to comment.