diff --git a/cowmap_bench_test.go b/cowmap_bench_test.go new file mode 100644 index 0000000..c44ac48 --- /dev/null +++ b/cowmap_bench_test.go @@ -0,0 +1,212 @@ +package eventbus + +import ( + "strconv" + "sync" + "testing" +) + +func BenchmarkSingleGoroutineStoreAbsentByMap(b *testing.B) { + m := make(map[string]any) + b.ResetTimer() + for i := 0; i < b.N; i++ { + m[strconv.Itoa(i)] = "value" + } +} + +func BenchmarkSingleGoroutineStoreAbsentBySyncMap(b *testing.B) { + var m sync.Map + b.ResetTimer() + for i := 0; i < b.N; i++ { + m.Store(strconv.Itoa(i), "value") + } +} + +func BenchmarkSingleGoroutineStoreAbsentByCowMap(b *testing.B) { + m := NewCowMap() + b.ResetTimer() + for i := 0; i < b.N; i++ { + m.Store(strconv.Itoa(i), "value") + } +} + +func BenchmarkSingleGoroutineStorePresentByMap(b *testing.B) { + m := make(map[string]any) + m["key"] = "value" + b.ResetTimer() + for i := 0; i < b.N; i++ { + m["key"] = "value" + } +} + +func BenchmarkSingleGoroutineStorePresentBySyncMap(b *testing.B) { + var m sync.Map + m.Store("key", "value") + b.ResetTimer() + for i := 0; i < b.N; i++ { + m.Store("key", "value") + } +} + +func BenchmarkSingleGoroutineStorePresentByCowMap(b *testing.B) { + m := NewCowMap() + m.Store("key", "value") + b.ResetTimer() + for i := 0; i < b.N; i++ { + m.Store("key", "value") + } +} + +func BenchmarkMultiGoroutineLoadDifferentBySyncMap(b *testing.B) { + var m sync.Map + finished := make(chan struct{}, b.N) + for i := 0; i < 1000; i++ { + m.Store(i, i) + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + go func() { + for j := 0; j < 1000; j++ { + m.Load(j) + } + finished <- struct{}{} + }() + } + for i := 0; i < b.N; i++ { + <-finished + } +} + +func BenchmarkMultiGoroutineLoadDifferentByCowMap(b *testing.B) { + m := NewCowMap() + finished := make(chan struct{}, b.N) + for i := 0; i < 1000; i++ { + m.Store(i, i) + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + go func() { + for j := 0; j < 1000; j++ { + m.Load(j) + } + finished <- struct{}{} + }() + } + for i := 0; i < b.N; i++ { + <-finished + } +} + +func BenchmarkMultiGoroutineLoadSameBySyncMap(b *testing.B) { + var m sync.Map + finished := make(chan struct{}, b.N) + m.Store("key", "value") + b.ResetTimer() + for i := 0; i < b.N; i++ { + go func() { + for i := 0; i < 10; i++ { + m.Load("key") + } + finished <- struct{}{} + }() + } + for i := 0; i < b.N; i++ { + <-finished + } +} + +func BenchmarkMultiGoroutineLoadSameByCowMap(b *testing.B) { + m := NewCowMap() + finished := make(chan struct{}, b.N) + m.Store("key", "value") + b.ResetTimer() + for i := 0; i < b.N; i++ { + go func() { + for i := 0; i < 10; i++ { + m.Load("key") + } + finished <- struct{}{} + }() + } + for i := 0; i < b.N; i++ { + <-finished + } +} + +func Benchmark_CowMapStore(b *testing.B) { + m := NewCowMap() + b.ResetTimer() + for i := 0; i < b.N; i++ { + m.Store(i, strconv.Itoa(i)) + } +} + +func Benchmark_CowMapLoad(b *testing.B) { + m := NewCowMap() + for i := 0; i < 1000; i++ { + m.Store(i, strconv.Itoa(i)) + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + m.Load(i % 1000) + } +} + +func Benchmark_SyncMapStore(b *testing.B) { + var m sync.Map + b.ResetTimer() + for i := 0; i < b.N; i++ { + m.Store(i, strconv.Itoa(i)) + } +} + +func Benchmark_SyncMapLoad(b *testing.B) { + var m sync.Map + for i := 0; i < 1000; i++ { + m.Store(i, strconv.Itoa(i)) + } + + b.ResetTimer() + for i := 0; i < b.N; i++ { + m.Load(i % 1000) + } +} + +// func BenchmarkMultiGoroutineStoreDifferentBySyncMap(b *testing.B) { +// var m sync.Map +// finished := make(chan struct{}, b.N) + +// b.ResetTimer() +// for i := 0; i < b.N; i++ { +// go func(k string, v any) { +// for i := 0; i < 10; i++ { +// m.Store(k, v) +// } +// finished <- struct{}{} +// }(strconv.Itoa(i), "value") +// } +// for i := 0; i < b.N; i++ { +// <-finished +// } +// } + +// func BenchmarkMultiGoroutineStoreDifferentByCowMap(b *testing.B) { +// m := NewCowMap() +// finished := make(chan struct{}, b.N) + +// b.ResetTimer() +// for i := 0; i < b.N; i++ { +// go func(k string, v any) { +// for i := 0; i < 10; i++ { +// m.Store(k, v) +// } +// finished <- struct{}{} +// }(strconv.Itoa(i), "value") +// } +// for i := 0; i < b.N; i++ { +// <-finished +// } +// } diff --git a/cowmap_test.go b/cowmap_test.go index d7317bd..8304ba3 100644 --- a/cowmap_test.go +++ b/cowmap_test.go @@ -246,23 +246,3 @@ func Test_CowMapStoreAndLoadConcurrent(t *testing.T) { loadWg.Wait() }) } - -func Benchmark_CowMapStore(b *testing.B) { - m := NewCowMap() - b.ResetTimer() - for i := 0; i < b.N; i++ { - m.Store(i, strconv.Itoa(i)) - } -} - -func Benchmark_CowMapLoad(b *testing.B) { - m := NewCowMap() - for i := 0; i < 100; i++ { - m.Store(i, strconv.Itoa(i)) - } - - b.ResetTimer() - for i := 0; i < b.N; i++ { - m.Load(i % 100) - } -} diff --git a/pipe_bench_test.go b/pipe_bench_test.go new file mode 100644 index 0000000..dd61b1d --- /dev/null +++ b/pipe_bench_test.go @@ -0,0 +1,43 @@ +package eventbus + +import ( + "testing" +) + +func BenchmarkPipePublishSync(b *testing.B) { + pipe := NewPipe[int]() + + pipe.Subscribe(pipeHandlerOne) + + b.ResetTimer() + for i := 0; i < b.N; i++ { + pipe.PublishSync(i) + } +} + +func BenchmarkPipePublish(b *testing.B) { + pipe := NewPipe[int]() + + pipe.Subscribe(pipeHandlerOne) + + b.ResetTimer() + for i := 0; i < b.N; i++ { + pipe.Publish(i) + } +} + +func BenchmarkPipeGoChannel(b *testing.B) { + ch := make(chan int) + + go func() { + for { + val := <-ch + pipeHandlerOne(val) + } + }() + + b.ResetTimer() + for i := 0; i < b.N; i++ { + ch <- i + } +} diff --git a/pipe_test.go b/pipe_test.go index 11b0630..05e64a2 100644 --- a/pipe_test.go +++ b/pipe_test.go @@ -130,30 +130,3 @@ func Test_PipeClose(t *testing.T) { assert.Equal(t, ErrChannelClosed, err) p.Close() } - -func BenchmarkPipePublish(b *testing.B) { - pipe := NewPipe[int]() - - pipe.Subscribe(pipeHandlerOne) - - b.ResetTimer() - for i := 0; i < b.N; i++ { - pipe.PublishSync(i) - } -} - -func BenchmarkPipeGoChannel(b *testing.B) { - ch := make(chan int) - - go func() { - for { - val := <-ch - pipeHandlerOne(val) - } - }() - - b.ResetTimer() - for i := 0; i < b.N; i++ { - ch <- i - } -}