Skip to content

Instantly share code, notes, and snippets.

@yyforyongyu
Created January 18, 2023 21:49
Show Gist options
  • Save yyforyongyu/1029d1b1508ed5bcb8f26c8114a3bfb6 to your computer and use it in GitHub Desktop.
Save yyforyongyu/1029d1b1508ed5bcb8f26c8114a3bfb6 to your computer and use it in GitHub Desktop.
Benchmark performance among sync map, mutex map and read-write mutex map.
package main
import (
"sync"
"sync/atomic"
"testing"
)
func BenchmarkReadMutexMap(b *testing.B) {
// Create a map with a mutex.
m := make(map[int64]struct{})
// k is the unique key for each goroutine.
k := int64(0)
// Create a general mutex.
var mu sync.Mutex
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
// Increment k.
atomic.AddInt64(&k, 1)
// Perform a lock read.
mu.Lock()
_, _ = m[k]
mu.Unlock()
}
})
}
func BenchmarkReadRWMutexMap(b *testing.B) {
// Create a map with a mutex.
m := make(map[int64]struct{})
// k is the unique key for each goroutine.
k := int64(0)
// Create a read write mutex.
var mu sync.RWMutex
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
// Increment k.
atomic.AddInt64(&k, 1)
// Perform a lock read.
mu.RLock()
_, _ = m[k]
mu.RUnlock()
}
})
}
func BenchmarkReadSyncMap(b *testing.B) {
// Create a sync.Map.
syncMap := &sync.Map{}
// k is the unique key for each goroutine.
k := int64(0)
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
// Increment k.
atomic.AddInt64(&k, 1)
// Read the value.
syncMap.Load(k)
}
})
}
func BenchmarkWriteMutexMap(b *testing.B) {
// Create a map with a mutex.
m := make(map[int64]struct{})
// k is the unique key for each goroutine.
k := int64(0)
// Create a general mutex.
var mu sync.Mutex
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
// Increment k.
atomic.AddInt64(&k, 1)
// Perform a lock write.
mu.Lock()
m[k] = struct{}{}
mu.Unlock()
}
})
}
func BenchmarkWriteRWMutexMap(b *testing.B) {
// Create a map with a mutex.
m := make(map[int64]struct{})
// k is the unique key for each goroutine.
k := int64(0)
// Create a read write mutex.
var mu sync.RWMutex
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
// Increment k.
atomic.AddInt64(&k, 1)
// Perform a lock write.
mu.Lock()
m[k] = struct{}{}
mu.Unlock()
}
})
}
func BenchmarkWriteSyncMap(b *testing.B) {
// Create a sync.Map.
syncMap := &sync.Map{}
// k is the unique key for each goroutine.
k := int64(0)
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
// Increment k.
atomic.AddInt64(&k, 1)
// Write the value.
syncMap.Store(k, struct{}{})
}
})
}
func BenchmarkDeleteMutexMap(b *testing.B) {
// Create a map with a mutex.
m := make(map[int64]struct{})
// k is the unique key for each goroutine.
k := int64(0)
// Create a general mutex.
var mu sync.Mutex
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
// Increment k.
atomic.AddInt64(&k, 1)
// Perform a lock delete.
mu.Lock()
delete(m, k)
mu.Unlock()
}
})
}
func BenchmarkDeleteRWMutexMap(b *testing.B) {
// Create a map with a mutex.
m := make(map[int64]struct{})
// k is the unique key for each goroutine.
k := int64(0)
// Create a read write mutex.
var mu sync.RWMutex
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
// Increment k.
atomic.AddInt64(&k, 1)
// Perform a lock delete.
mu.Lock()
delete(m, k)
mu.Unlock()
}
})
}
func BenchmarkDeleteSyncMap(b *testing.B) {
// Create a sync.Map.
syncMap := &sync.Map{}
// k is the unique key for each goroutine.
k := int64(0)
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
// Increment k.
atomic.AddInt64(&k, 1)
// Delete the value.
syncMap.Delete(k)
}
})
}
// TODO: can further benchmark based on the map's state, such as,
// - read a key that exists.
// - write a key that exists.
// - delete a key that exists.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment