Skip to content

Commit

Permalink
test(tm2/pkg/cmap): adds benchmarks to show true impact of contention
Browse files Browse the repository at this point in the history
The Go standard library's sync.Map is touted as great for cases with
high load and is commonly known knowledge but the benchmark that I am
committing shows otherwise that for this library's usage, it is so much
more expensive hence this benchmark will avoid someone committing
sync.Map without seeing the true implications.

```shell
$ benchstat map_w_mutex.txt stdlib_sync_map.txt
name                               old time/op    new time/op    delta
CMapConcurrentInsertsDeletesHas-8     1.72s ±11%     1.92s ± 3%   +11.66%  (p=0.000 n=10+9)
CMapHas-8                             109ns ± 9%     118ns ± 3%    +8.26%  (p=0.002 n=10+8)

name                               old alloc/op   new alloc/op   delta
CMapConcurrentInsertsDeletesHas-8    1.18GB ± 2%    3.21GB ± 3%  +172.09%  (p=0.000 n=10+10)
CMapHas-8                             16.0B ± 0%     16.0B ± 0%      ~     (all equal)

name                               old allocs/op  new allocs/op  delta
CMapConcurrentInsertsDeletesHas-8      824k ± 0%     4433k ± 0%  +437.89%  (p=0.000 n=10+10)
CMapHas-8                              2.00 ± 0%      1.60 ±38%      ~     (p=0.065 n=9+10)
```

Updates gnolang#3505
  • Loading branch information
odeke-em committed Jan 17, 2025
1 parent 870cbed commit e05a9cc
Showing 1 changed file with 57 additions and 0 deletions.
57 changes: 57 additions & 0 deletions tm2/pkg/cmap/cmap_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ package cmap

import (
"fmt"
"runtime"
"strings"
"sync"
"testing"

"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -56,6 +58,61 @@ func TestContains(t *testing.T) {
assert.Nil(t, cmap.Get("key2"))
}

var sink any = nil

func BenchmarkCMapConcurrentInsertsDeletesHas(b *testing.B) {
cm := NewCMap()
keys := make([]string, 100000)
for i := range keys {
keys[i] = fmt.Sprintf("key%d", i)
}
b.ResetTimer()

for i := 0; i < b.N; i++ {
var wg sync.WaitGroup
semaCh := make(chan bool)
nCPU := runtime.NumCPU()
for j := 0; j < nCPU; j++ {
wg.Add(1)
go func() {
defer wg.Done()

// Make sure that all the goroutines run at the
// exact same time for true concurrent tests.
<-semaCh

for i, key := range keys {
if (j+i)%2 == 0 {
cm.Has(key)
} else {
cm.Set(key, j)
}
_ = cm.Size()
if (i+1)%3 == 0 {
cm.Delete(key)
}

if (i+1)%327 == 0 {
cm.Clear()
}
_ = cm.Size()
_ = cm.Keys()
}
_ = cm.Values()
}()
}
close(semaCh)
wg.Wait()

sink = wg
}

if sink == nil {
b.Fatal("Benchmark did not run!")
}
sink = nil
}

func BenchmarkCMapHas(b *testing.B) {
m := NewCMap()
for i := 0; i < 1000; i++ {
Expand Down

0 comments on commit e05a9cc

Please sign in to comment.