123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344 |
- package hashmap
- import (
- "strconv"
- "sync"
- "sync/atomic"
- "testing"
- )
- const benchmarkItemCount = 1 << 10 // 1024
- func setupHashMap(b *testing.B) *HashMap {
- m := &HashMap{}
- for i := uintptr(0); i < benchmarkItemCount; i++ {
- m.Set(i, i)
- }
- b.ResetTimer()
- return m
- }
- func setupHashMapString(b *testing.B) (*HashMap, []string) {
- m := &HashMap{}
- keys := make([]string, benchmarkItemCount)
- for i := 0; i < benchmarkItemCount; i++ {
- s := strconv.Itoa(i)
- m.Set(s, s)
- keys[i] = s
- }
- b.ResetTimer()
- return m, keys
- }
- func setupHashMapHashedKey(b *testing.B) *HashMap {
- m := &HashMap{}
- log := log2(uintptr(benchmarkItemCount))
- for i := uintptr(0); i < benchmarkItemCount; i++ {
- hash := i << (strconv.IntSize - log)
- m.SetHashedKey(hash, i)
- }
- b.ResetTimer()
- return m
- }
- func setupGoMap(b *testing.B) map[uintptr]uintptr {
- m := make(map[uintptr]uintptr)
- for i := uintptr(0); i < benchmarkItemCount; i++ {
- m[i] = i
- }
- b.ResetTimer()
- return m
- }
- func setupGoSyncMap(b *testing.B) *sync.Map {
- m := &sync.Map{}
- for i := uintptr(0); i < benchmarkItemCount; i++ {
- m.Store(i, i)
- }
- b.ResetTimer()
- return m
- }
- func setupGoMapString(b *testing.B) (map[string]string, []string) {
- m := make(map[string]string)
- keys := make([]string, benchmarkItemCount)
- for i := 0; i < benchmarkItemCount; i++ {
- s := strconv.Itoa(i)
- m[s] = s
- keys[i] = s
- }
- b.ResetTimer()
- return m, keys
- }
- func BenchmarkReadHashMapUint(b *testing.B) {
- m := setupHashMap(b)
- b.RunParallel(func(pb *testing.PB) {
- for pb.Next() {
- for i := uintptr(0); i < benchmarkItemCount; i++ {
- j, _ := m.GetUintKey(i)
- if j != i {
- b.Fail()
- }
- }
- }
- })
- }
- func BenchmarkReadHashMapWithWritesUint(b *testing.B) {
- m := setupHashMap(b)
- var writer uintptr
- b.RunParallel(func(pb *testing.PB) {
- // use 1 thread as writer
- if atomic.CompareAndSwapUintptr(&writer, 0, 1) {
- for pb.Next() {
- for i := uintptr(0); i < benchmarkItemCount; i++ {
- m.Set(i, i)
- }
- }
- } else {
- for pb.Next() {
- for i := uintptr(0); i < benchmarkItemCount; i++ {
- j, _ := m.GetUintKey(i)
- if j != i {
- b.Fail()
- }
- }
- }
- }
- })
- }
- func BenchmarkReadHashMapString(b *testing.B) {
- m, keys := setupHashMapString(b)
- b.RunParallel(func(pb *testing.PB) {
- for pb.Next() {
- for i := 0; i < benchmarkItemCount; i++ {
- s := keys[i]
- sVal, _ := m.GetStringKey(s)
- if sVal != s {
- b.Fail()
- }
- }
- }
- })
- }
- func BenchmarkReadHashMapInterface(b *testing.B) {
- m := setupHashMap(b)
- b.RunParallel(func(pb *testing.PB) {
- for pb.Next() {
- for i := uintptr(0); i < benchmarkItemCount; i++ {
- j, _ := m.Get(i)
- if j != i {
- b.Fail()
- }
- }
- }
- })
- }
- func BenchmarkReadHashMapHashedKey(b *testing.B) {
- m := setupHashMapHashedKey(b)
- log := log2(uintptr(benchmarkItemCount))
- b.RunParallel(func(pb *testing.PB) {
- for pb.Next() {
- for i := uintptr(0); i < benchmarkItemCount; i++ {
- hash := i << (strconv.IntSize - log)
- j, _ := m.GetHashedKey(hash)
- if j != i {
- b.Fail()
- }
- }
- }
- })
- }
- func BenchmarkReadGoMapUintUnsafe(b *testing.B) {
- m := setupGoMap(b)
- b.RunParallel(func(pb *testing.PB) {
- for pb.Next() {
- for i := uintptr(0); i < benchmarkItemCount; i++ {
- j := m[i]
- if j != i {
- b.Fail()
- }
- }
- }
- })
- }
- func BenchmarkReadGoMapUintMutex(b *testing.B) {
- m := setupGoMap(b)
- l := &sync.RWMutex{}
- b.RunParallel(func(pb *testing.PB) {
- for pb.Next() {
- for i := uintptr(0); i < benchmarkItemCount; i++ {
- l.RLock()
- j := m[i]
- l.RUnlock()
- if j != i {
- b.Fail()
- }
- }
- }
- })
- }
- func BenchmarkReadGoMapWithWritesUintMutex(b *testing.B) {
- m := setupGoMap(b)
- l := &sync.RWMutex{}
- var writer uintptr
- b.RunParallel(func(pb *testing.PB) {
- // use 1 thread as writer
- if atomic.CompareAndSwapUintptr(&writer, 0, 1) {
- for pb.Next() {
- for i := uintptr(0); i < benchmarkItemCount; i++ {
- l.Lock()
- m[i] = i
- l.Unlock()
- }
- }
- } else {
- for pb.Next() {
- for i := uintptr(0); i < benchmarkItemCount; i++ {
- l.RLock()
- j := m[i]
- l.RUnlock()
- if j != i {
- b.Fail()
- }
- }
- }
- }
- })
- }
- func BenchmarkReadGoSyncMapUint(b *testing.B) {
- m := setupGoSyncMap(b)
- b.RunParallel(func(pb *testing.PB) {
- for pb.Next() {
- for i := uintptr(0); i < benchmarkItemCount; i++ {
- j, _ := m.Load(i)
- if j != i {
- b.Fail()
- }
- }
- }
- })
- }
- func BenchmarkReadGoSyncMapWithWritesUint(b *testing.B) {
- m := setupGoSyncMap(b)
- var writer uintptr
- b.RunParallel(func(pb *testing.PB) {
- // use 1 thread as writer
- if atomic.CompareAndSwapUintptr(&writer, 0, 1) {
- for pb.Next() {
- for i := uintptr(0); i < benchmarkItemCount; i++ {
- m.Store(i, i)
- }
- }
- } else {
- for pb.Next() {
- for i := uintptr(0); i < benchmarkItemCount; i++ {
- j, _ := m.Load(i)
- if j != i {
- b.Fail()
- }
- }
- }
- }
- })
- }
- func BenchmarkReadGoMapStringUnsafe(b *testing.B) {
- m, keys := setupGoMapString(b)
- b.RunParallel(func(pb *testing.PB) {
- for pb.Next() {
- for i := 0; i < benchmarkItemCount; i++ {
- s := keys[i]
- sVal := m[s]
- if s != sVal {
- b.Fail()
- }
- }
- }
- })
- }
- func BenchmarkReadGoMapStringMutex(b *testing.B) {
- m, keys := setupGoMapString(b)
- l := &sync.RWMutex{}
- b.RunParallel(func(pb *testing.PB) {
- for pb.Next() {
- for i := 0; i < benchmarkItemCount; i++ {
- s := keys[i]
- l.RLock()
- sVal := m[s]
- l.RUnlock()
- if s != sVal {
- b.Fail()
- }
- }
- }
- })
- }
- func BenchmarkWriteHashMapUint(b *testing.B) {
- m := &HashMap{}
- for n := 0; n < b.N; n++ {
- for i := uintptr(0); i < benchmarkItemCount; i++ {
- m.Set(i, i)
- }
- }
- }
- func BenchmarkWriteHashMapHashedKey(b *testing.B) {
- m := &HashMap{}
- log := log2(uintptr(benchmarkItemCount))
- for n := 0; n < b.N; n++ {
- for i := uintptr(0); i < benchmarkItemCount; i++ {
- hash := i << (strconv.IntSize - log)
- m.SetHashedKey(hash, i)
- }
- }
- }
- func BenchmarkWriteGoMapMutexUint(b *testing.B) {
- m := make(map[uintptr]uintptr)
- l := &sync.RWMutex{}
- for n := 0; n < b.N; n++ {
- for i := uintptr(0); i < benchmarkItemCount; i++ {
- l.Lock()
- m[i] = i
- l.Unlock()
- }
- }
- }
- func BenchmarkWriteGoSyncMapUint(b *testing.B) {
- m := &sync.Map{}
- for n := 0; n < b.N; n++ {
- for i := uintptr(0); i < benchmarkItemCount; i++ {
- m.Store(i, i)
- }
- }
- }
|