Skip to content

Commit e90d44f

Browse files
committed
update benchmarks
1 parent 152772b commit e90d44f

File tree

4 files changed

+37
-25
lines changed

4 files changed

+37
-25
lines changed

README.md

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -45,26 +45,26 @@ Reading from the hash map in a thread-safe way is nearly as fast as reading from
4545
in an unsafe way and twice as fast as Go's `sync.Map`:
4646

4747
```
48-
BenchmarkReadHashMapUint-8 2047108 547.2 ns/op
49-
BenchmarkReadHaxMapUint-8 2295067 532.3 ns/op (not safe to use, can lose writes during concurrent deletes)
50-
BenchmarkReadGoMapUintUnsafe-8 3303577 360.6 ns/op
51-
BenchmarkReadGoMapUintMutex-8 83017 14266 ns/op
52-
BenchmarkReadGoSyncMapUint-8 943773 1208 ns/op
48+
BenchmarkReadHashMapUint-8 1314156 955.6 ns/op
49+
BenchmarkReadHaxMapUint-8 872134 1316 ns/op (can not handle hash 0 collisions)
50+
BenchmarkReadGoMapUintUnsafe-8 1560886 762.8 ns/op
51+
BenchmarkReadGoMapUintMutex-8 42284 28232 ns/op
52+
BenchmarkReadGoSyncMapUint-8 468338 2672 ns/op
5353
```
5454

5555
Reading from the map while writes are happening:
5656
```
57-
BenchmarkReadHashMapWithWritesUint-8 1669750 718.1 ns/op
58-
BenchmarkReadGoMapWithWritesUintMutex-8 24919 54270 ns/op
59-
BenchmarkReadGoSyncMapWithWritesUint-8 823063 1439 ns/op
57+
BenchmarkReadHashMapWithWritesUint-8 890938 1288 ns/op
58+
BenchmarkReadGoMapWithWritesUintMutex-8 14290 86758 ns/op
59+
BenchmarkReadGoSyncMapWithWritesUint-8 374464 3149 ns/op
6060
```
6161

6262
Write performance without any concurrent reads:
6363

6464
```
65-
BenchmarkWriteHashMapUint-8 30104 49176 ns/op
66-
BenchmarkWriteGoMapMutexUint-8 177536 6571 ns/op
67-
BenchmarkWriteGoSyncMapUint-8 19857 61428 ns/op
65+
BenchmarkWriteHashMapUint-8 15384 79032 ns/op
66+
BenchmarkWriteGoMapMutexUint-8 74569 14874 ns/op
67+
BenchmarkWriteGoSyncMapUint-8 10000 107094 ns/op
6868
```
6969

7070
The benchmarks were run with Golang 1.19.0 on Linux using `make benchmark`.
@@ -73,7 +73,7 @@ The benchmarks were run with Golang 1.19.0 on Linux using `make benchmark`.
7373

7474
* Faster
7575

76-
* thread-safe access without need of a(n extra) mutex
76+
* thread-safe access without need of a mutex
7777

7878
### Benefits over [Golang's sync.Map](https://golang.org/pkg/sync/#Map)
7979

@@ -92,3 +92,5 @@ The benchmarks were run with Golang 1.19.0 on Linux using `make benchmark`.
9292
Once a slice is allocated, the size of it does not change.
9393
The library limits the index into the slice, therefore the Golang size check is obsolete.
9494
When the slice reaches a defined fill rate, a bigger slice is allocated and all keys are recalculated and transferred into the new slice.
95+
96+
* For hashing, specialized xxhash implementations are used that match the size of the key type where available

benchmarks/benchmark_test.go

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import (
1010
"github.com/cornelk/hashmap"
1111
)
1212

13-
const benchmarkItemCount = 512
13+
const benchmarkItemCount = 1024
1414

1515
func setupHashMap(b *testing.B) *hashmap.HashMap[uintptr, uintptr] {
1616
b.Helper()
@@ -19,8 +19,6 @@ func setupHashMap(b *testing.B) *hashmap.HashMap[uintptr, uintptr] {
1919
for i := uintptr(0); i < benchmarkItemCount; i++ {
2020
m.Set(i, i)
2121
}
22-
23-
b.ResetTimer()
2422
return m
2523
}
2624

@@ -45,7 +43,6 @@ func setupHashMapString(b *testing.B) (*hashmap.HashMap[string, string], []strin
4543
keys[i] = s
4644
}
4745

48-
b.ResetTimer()
4946
return m, keys
5047
}
5148

@@ -57,7 +54,6 @@ func setupGoMap(b *testing.B) map[uintptr]uintptr {
5754
m[i] = i
5855
}
5956

60-
b.ResetTimer()
6157
return m
6258
}
6359

@@ -69,7 +65,6 @@ func setupGoSyncMap(b *testing.B) *sync.Map {
6965
m.Store(i, i)
7066
}
7167

72-
b.ResetTimer()
7368
return m
7469
}
7570

@@ -83,12 +78,12 @@ func setupGoMapString(b *testing.B) (map[string]string, []string) {
8378
m[s] = s
8479
keys[i] = s
8580
}
86-
b.ResetTimer()
8781
return m, keys
8882
}
8983

9084
func BenchmarkReadHashMapUint(b *testing.B) {
9185
m := setupHashMap(b)
86+
b.ResetTimer()
9287

9388
b.RunParallel(func(pb *testing.PB) {
9489
for pb.Next() {
@@ -105,6 +100,7 @@ func BenchmarkReadHashMapUint(b *testing.B) {
105100
func BenchmarkReadHashMapWithWritesUint(b *testing.B) {
106101
m := setupHashMap(b)
107102
var writer uintptr
103+
b.ResetTimer()
108104

109105
b.RunParallel(func(pb *testing.PB) {
110106
// use 1 thread as writer
@@ -129,6 +125,7 @@ func BenchmarkReadHashMapWithWritesUint(b *testing.B) {
129125

130126
func BenchmarkReadHashMapString(b *testing.B) {
131127
m, keys := setupHashMapString(b)
128+
b.ResetTimer()
132129

133130
b.RunParallel(func(pb *testing.PB) {
134131
for pb.Next() {
@@ -145,6 +142,7 @@ func BenchmarkReadHashMapString(b *testing.B) {
145142

146143
func BenchmarkReadHashMapInterface(b *testing.B) {
147144
m := setupHashMap(b)
145+
b.ResetTimer()
148146

149147
b.RunParallel(func(pb *testing.PB) {
150148
for pb.Next() {
@@ -160,6 +158,7 @@ func BenchmarkReadHashMapInterface(b *testing.B) {
160158

161159
func BenchmarkReadHaxMapUint(b *testing.B) {
162160
m := setupHaxMap(b)
161+
b.ResetTimer()
163162

164163
b.RunParallel(func(pb *testing.PB) {
165164
for pb.Next() {
@@ -176,6 +175,7 @@ func BenchmarkReadHaxMapUint(b *testing.B) {
176175
func BenchmarkReadHaxMapWithWritesUint(b *testing.B) {
177176
m := setupHaxMap(b)
178177
var writer uintptr
178+
b.ResetTimer()
179179

180180
b.RunParallel(func(pb *testing.PB) {
181181
// use 1 thread as writer
@@ -200,6 +200,7 @@ func BenchmarkReadHaxMapWithWritesUint(b *testing.B) {
200200

201201
func BenchmarkReadGoMapUintUnsafe(b *testing.B) {
202202
m := setupGoMap(b)
203+
b.ResetTimer()
203204
b.RunParallel(func(pb *testing.PB) {
204205
for pb.Next() {
205206
for i := uintptr(0); i < benchmarkItemCount; i++ {
@@ -215,6 +216,7 @@ func BenchmarkReadGoMapUintUnsafe(b *testing.B) {
215216
func BenchmarkReadGoMapUintMutex(b *testing.B) {
216217
m := setupGoMap(b)
217218
l := &sync.RWMutex{}
219+
b.ResetTimer()
218220
b.RunParallel(func(pb *testing.PB) {
219221
for pb.Next() {
220222
for i := uintptr(0); i < benchmarkItemCount; i++ {
@@ -233,6 +235,7 @@ func BenchmarkReadGoMapWithWritesUintMutex(b *testing.B) {
233235
m := setupGoMap(b)
234236
l := &sync.RWMutex{}
235237
var writer uintptr
238+
b.ResetTimer()
236239

237240
b.RunParallel(func(pb *testing.PB) {
238241
// use 1 thread as writer
@@ -261,6 +264,7 @@ func BenchmarkReadGoMapWithWritesUintMutex(b *testing.B) {
261264

262265
func BenchmarkReadGoSyncMapUint(b *testing.B) {
263266
m := setupGoSyncMap(b)
267+
b.ResetTimer()
264268
b.RunParallel(func(pb *testing.PB) {
265269
for pb.Next() {
266270
for i := uintptr(0); i < benchmarkItemCount; i++ {
@@ -276,6 +280,7 @@ func BenchmarkReadGoSyncMapUint(b *testing.B) {
276280
func BenchmarkReadGoSyncMapWithWritesUint(b *testing.B) {
277281
m := setupGoSyncMap(b)
278282
var writer uintptr
283+
b.ResetTimer()
279284

280285
b.RunParallel(func(pb *testing.PB) {
281286
// use 1 thread as writer
@@ -300,6 +305,7 @@ func BenchmarkReadGoSyncMapWithWritesUint(b *testing.B) {
300305

301306
func BenchmarkReadGoMapStringUnsafe(b *testing.B) {
302307
m, keys := setupGoMapString(b)
308+
b.ResetTimer()
303309
b.RunParallel(func(pb *testing.PB) {
304310
for pb.Next() {
305311
for i := 0; i < benchmarkItemCount; i++ {
@@ -316,6 +322,7 @@ func BenchmarkReadGoMapStringUnsafe(b *testing.B) {
316322
func BenchmarkReadGoMapStringMutex(b *testing.B) {
317323
m, keys := setupGoMapString(b)
318324
l := &sync.RWMutex{}
325+
b.ResetTimer()
319326
b.RunParallel(func(pb *testing.PB) {
320327
for pb.Next() {
321328
for i := 0; i < benchmarkItemCount; i++ {
@@ -333,6 +340,7 @@ func BenchmarkReadGoMapStringMutex(b *testing.B) {
333340

334341
func BenchmarkWriteHashMapUint(b *testing.B) {
335342
m := hashmap.New[uintptr, uintptr]()
343+
b.ResetTimer()
336344

337345
for n := 0; n < b.N; n++ {
338346
for i := uintptr(0); i < benchmarkItemCount; i++ {
@@ -344,6 +352,7 @@ func BenchmarkWriteHashMapUint(b *testing.B) {
344352
func BenchmarkWriteGoMapMutexUint(b *testing.B) {
345353
m := make(map[uintptr]uintptr)
346354
l := &sync.RWMutex{}
355+
b.ResetTimer()
347356

348357
for n := 0; n < b.N; n++ {
349358
for i := uintptr(0); i < benchmarkItemCount; i++ {
@@ -356,6 +365,7 @@ func BenchmarkWriteGoMapMutexUint(b *testing.B) {
356365

357366
func BenchmarkWriteGoSyncMapUint(b *testing.B) {
358367
m := &sync.Map{}
368+
b.ResetTimer()
359369

360370
for n := 0; n < b.N; n++ {
361371
for i := uintptr(0); i < benchmarkItemCount; i++ {

benchmarks/go.mod

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@ module github.com/cornelk/hashmap/benchmarks
22

33
go 1.19
44

5+
replace github.com/cornelk/hashmap => ../
6+
57
require (
6-
github.com/alphadose/haxmap v0.1.1-0.20220808155550-bc3b9a6adfc4
7-
github.com/cornelk/hashmap v1.0.4-0.20220810053739-f969cadbb3f0
8+
github.com/alphadose/haxmap v0.2.1-0.20220828165710-add810974d4f
9+
github.com/cornelk/hashmap v1.0.5-0.20220828215932-152772b42884
810
)
911

1012
require github.com/cespare/xxhash v1.1.0 // indirect

benchmarks/go.sum

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE=
22
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
3-
github.com/alphadose/haxmap v0.1.1-0.20220808155550-bc3b9a6adfc4 h1:E78W2LuJFjDKpr0a0xFK9w0rawO4wtmTdcbRX5H11mg=
4-
github.com/alphadose/haxmap v0.1.1-0.20220808155550-bc3b9a6adfc4/go.mod h1:68nFwlFwh/HEilKSdlNOKnd1PwOy8EUnKUtZH2TdVb8=
3+
github.com/alphadose/haxmap v0.2.1-0.20220828165710-add810974d4f h1:up6qKu3lIXQ4H3AyJovBy0Tp6Ug++aveneLrUv7TyNo=
4+
github.com/alphadose/haxmap v0.2.1-0.20220828165710-add810974d4f/go.mod h1:Fu37Wlmj7cR++vSLgRTu3fGy8wpjHGmMypM2aclkc1A=
55
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
66
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
7-
github.com/cornelk/hashmap v1.0.4-0.20220810053739-f969cadbb3f0 h1:jed6FFAMwRgg57mgmqH/kfSsjtXL8ocT3f2zE/8vumg=
8-
github.com/cornelk/hashmap v1.0.4-0.20220810053739-f969cadbb3f0/go.mod h1:T9KPzj/SjvCwiF51NdfFMmqHhRm6cl2slzzgmmgDnUw=
97
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
108
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
119
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72 h1:qLC7fQah7D6K1B0ujays3HV9gkFtllcxhzImRR7ArPQ=

0 commit comments

Comments
 (0)