github.com/songzhibin97/go-baseutils@v0.0.2-0.20240302024150-487d8ce9c082/structure/maps/skipmap/skipmap_bench_test.go (about) 1 package skipmap 2 3 import ( 4 "math" 5 "strconv" 6 "sync" 7 "testing" 8 9 "github.com/songzhibin97/go-baseutils/base/bcomparator" 10 "github.com/songzhibin97/go-baseutils/sys/fastrand" 11 ) 12 13 const initsize = 1 << 10 // for `load` `1Delete9Store90Load` `1Range9Delete90Store900Load` 14 const randN = math.MaxUint32 15 16 func BenchmarkStore(b *testing.B) { 17 b.Run("skipmap", func(b *testing.B) { 18 l := New[int64, any](bcomparator.Int64Comparator()) 19 b.ResetTimer() 20 b.RunParallel(func(pb *testing.PB) { 21 for pb.Next() { 22 l.Store(int64(fastrand.Uint32n(randN)), nil) 23 } 24 }) 25 }) 26 b.Run("sync.Map", func(b *testing.B) { 27 var l sync.Map 28 b.ResetTimer() 29 b.RunParallel(func(pb *testing.PB) { 30 for pb.Next() { 31 l.Store(int64(fastrand.Uint32n(randN)), nil) 32 } 33 }) 34 }) 35 } 36 37 func BenchmarkLoad100Hits(b *testing.B) { 38 b.Run("skipmap", func(b *testing.B) { 39 l := New[int64, any](bcomparator.Int64Comparator()) 40 for i := 0; i < initsize; i++ { 41 l.Store(int64(i), nil) 42 } 43 b.ResetTimer() 44 b.RunParallel(func(pb *testing.PB) { 45 for pb.Next() { 46 _, _ = l.Load(int64(fastrand.Uint32n(initsize))) 47 } 48 }) 49 }) 50 b.Run("sync.Map", func(b *testing.B) { 51 var l sync.Map 52 for i := 0; i < initsize; i++ { 53 l.Store(int64(i), nil) 54 } 55 b.ResetTimer() 56 b.RunParallel(func(pb *testing.PB) { 57 for pb.Next() { 58 _, _ = l.Load(int64(fastrand.Uint32n(initsize))) 59 } 60 }) 61 }) 62 } 63 64 func BenchmarkLoad50Hits(b *testing.B) { 65 const rate = 2 66 b.Run("skipmap", func(b *testing.B) { 67 l := New[int64, any](bcomparator.Int64Comparator()) 68 for i := 0; i < initsize*rate; i++ { 69 if fastrand.Uint32n(rate) == 0 { 70 l.Store(int64(i), nil) 71 } 72 } 73 b.ResetTimer() 74 b.RunParallel(func(pb *testing.PB) { 75 for pb.Next() { 76 _, _ = l.Load(int64(fastrand.Uint32n(initsize * rate))) 77 } 78 }) 79 }) 80 b.Run("sync.Map", func(b *testing.B) { 81 var l sync.Map 82 for i := 0; i < initsize*rate; i++ { 83 if fastrand.Uint32n(rate) == 0 { 84 l.Store(int64(i), nil) 85 } 86 } 87 b.ResetTimer() 88 b.RunParallel(func(pb *testing.PB) { 89 for pb.Next() { 90 _, _ = l.Load(int64(fastrand.Uint32n(initsize * rate))) 91 } 92 }) 93 }) 94 } 95 96 func BenchmarkLoadNoHits(b *testing.B) { 97 b.Run("skipmap", func(b *testing.B) { 98 l := New[int64, any](bcomparator.Int64Comparator()) 99 invalid := make([]int64, 0, initsize) 100 for i := 0; i < initsize*2; i++ { 101 if i%2 == 0 { 102 l.Store(int64(i), nil) 103 } else { 104 invalid = append(invalid, int64(i)) 105 } 106 } 107 b.ResetTimer() 108 b.RunParallel(func(pb *testing.PB) { 109 for pb.Next() { 110 _, _ = l.Load(invalid[fastrand.Uint32n(uint32(len(invalid)))]) 111 } 112 }) 113 }) 114 b.Run("sync.Map", func(b *testing.B) { 115 var l sync.Map 116 invalid := make([]int64, 0, initsize) 117 for i := 0; i < initsize*2; i++ { 118 if i%2 == 0 { 119 l.Store(int64(i), nil) 120 } else { 121 invalid = append(invalid, int64(i)) 122 } 123 } 124 b.ResetTimer() 125 b.RunParallel(func(pb *testing.PB) { 126 for pb.Next() { 127 _, _ = l.Load(invalid[fastrand.Uint32n(uint32(len(invalid)))]) 128 } 129 }) 130 }) 131 } 132 133 func Benchmark50Store50Load(b *testing.B) { 134 b.Run("skipmap", func(b *testing.B) { 135 l := New[int64, any](bcomparator.Int64Comparator()) 136 b.ResetTimer() 137 b.RunParallel(func(pb *testing.PB) { 138 for pb.Next() { 139 u := fastrand.Uint32n(10) 140 if u < 5 { 141 l.Store(int64(fastrand.Uint32n(randN)), nil) 142 } else { 143 l.Load(int64(fastrand.Uint32n(randN))) 144 } 145 } 146 }) 147 }) 148 b.Run("sync.Map", func(b *testing.B) { 149 var l sync.Map 150 b.ResetTimer() 151 b.RunParallel(func(pb *testing.PB) { 152 for pb.Next() { 153 u := fastrand.Uint32n(10) 154 if u < 5 { 155 l.Store(int64(fastrand.Uint32n(randN)), nil) 156 } else { 157 l.Load(int64(fastrand.Uint32n(randN))) 158 } 159 } 160 }) 161 }) 162 } 163 164 func Benchmark30Store70Load(b *testing.B) { 165 b.Run("skipmap", func(b *testing.B) { 166 l := New[int64, any](bcomparator.Int64Comparator()) 167 b.ResetTimer() 168 b.RunParallel(func(pb *testing.PB) { 169 for pb.Next() { 170 u := fastrand.Uint32n(10) 171 if u < 3 { 172 l.Store(int64(fastrand.Uint32n(randN)), nil) 173 } else { 174 l.Load(int64(fastrand.Uint32n(randN))) 175 } 176 } 177 }) 178 }) 179 b.Run("sync.Map", func(b *testing.B) { 180 var l sync.Map 181 b.ResetTimer() 182 b.RunParallel(func(pb *testing.PB) { 183 for pb.Next() { 184 u := fastrand.Uint32n(10) 185 if u < 3 { 186 l.Store(int64(fastrand.Uint32n(randN)), nil) 187 } else { 188 l.Load(int64(fastrand.Uint32n(randN))) 189 } 190 } 191 }) 192 }) 193 } 194 195 func Benchmark1Delete9Store90Load(b *testing.B) { 196 b.Run("skipmap", func(b *testing.B) { 197 l := New[int64, any](bcomparator.Int64Comparator()) 198 for i := 0; i < initsize; i++ { 199 l.Store(int64(i), nil) 200 } 201 b.ResetTimer() 202 b.RunParallel(func(pb *testing.PB) { 203 for pb.Next() { 204 u := fastrand.Uint32n(100) 205 if u < 9 { 206 l.Store(int64(fastrand.Uint32n(randN)), nil) 207 } else if u == 10 { 208 l.Delete(int64(fastrand.Uint32n(randN))) 209 } else { 210 l.Load(int64(fastrand.Uint32n(randN))) 211 } 212 } 213 }) 214 }) 215 b.Run("sync.Map", func(b *testing.B) { 216 var l sync.Map 217 for i := 0; i < initsize; i++ { 218 l.Store(int64(i), nil) 219 } 220 b.ResetTimer() 221 b.RunParallel(func(pb *testing.PB) { 222 for pb.Next() { 223 u := fastrand.Uint32n(100) 224 if u < 9 { 225 l.Store(int64(fastrand.Uint32n(randN)), nil) 226 } else if u == 10 { 227 l.Delete(int64(fastrand.Uint32n(randN))) 228 } else { 229 l.Load(int64(fastrand.Uint32n(randN))) 230 } 231 } 232 }) 233 }) 234 } 235 236 func Benchmark1Range9Delete90Store900Load(b *testing.B) { 237 b.Run("skipmap", func(b *testing.B) { 238 l := New[int64, any](bcomparator.Int64Comparator()) 239 for i := 0; i < initsize; i++ { 240 l.Store(int64(i), nil) 241 } 242 b.ResetTimer() 243 b.RunParallel(func(pb *testing.PB) { 244 for pb.Next() { 245 u := fastrand.Uint32n(1000) 246 if u == 0 { 247 l.Range(func(key int64, value interface{}) bool { 248 return true 249 }) 250 } else if u > 10 && u < 20 { 251 l.Delete(int64(fastrand.Uint32n(randN))) 252 } else if u >= 100 && u < 190 { 253 l.Store(int64(fastrand.Uint32n(randN)), nil) 254 } else { 255 l.Load(int64(fastrand.Uint32n(randN))) 256 } 257 } 258 }) 259 }) 260 b.Run("sync.Map", func(b *testing.B) { 261 var l sync.Map 262 for i := 0; i < initsize; i++ { 263 l.Store(int64(i), nil) 264 } 265 b.ResetTimer() 266 b.RunParallel(func(pb *testing.PB) { 267 for pb.Next() { 268 u := fastrand.Uint32n(1000) 269 if u == 0 { 270 l.Range(func(key, value interface{}) bool { 271 return true 272 }) 273 } else if u > 10 && u < 20 { 274 l.Delete(int64(fastrand.Uint32n(randN))) 275 } else if u >= 100 && u < 190 { 276 l.Store(int64(fastrand.Uint32n(randN)), nil) 277 } else { 278 l.Load(int64(fastrand.Uint32n(randN))) 279 } 280 } 281 }) 282 }) 283 } 284 285 func BenchmarkStringStore(b *testing.B) { 286 b.Run("skipmap", func(b *testing.B) { 287 l := New[string, any](bcomparator.StringComparator()) 288 b.ResetTimer() 289 b.RunParallel(func(pb *testing.PB) { 290 for pb.Next() { 291 l.Store(strconv.Itoa(int(fastrand.Uint32())), nil) 292 } 293 }) 294 }) 295 b.Run("sync.Map", func(b *testing.B) { 296 var l sync.Map 297 b.ResetTimer() 298 b.RunParallel(func(pb *testing.PB) { 299 for pb.Next() { 300 l.Store(strconv.Itoa(int(fastrand.Uint32())), nil) 301 } 302 }) 303 }) 304 } 305 306 func BenchmarkStringLoad50Hits(b *testing.B) { 307 const rate = 2 308 b.Run("skipmap", func(b *testing.B) { 309 l := New[string, any](bcomparator.StringComparator()) 310 for i := 0; i < initsize*rate; i++ { 311 if fastrand.Uint32n(rate) == 0 { 312 l.Store(strconv.Itoa(i), nil) 313 } 314 } 315 b.ResetTimer() 316 b.RunParallel(func(pb *testing.PB) { 317 for pb.Next() { 318 _, _ = l.Load(strconv.Itoa(int(fastrand.Uint32n(initsize * rate)))) 319 } 320 }) 321 }) 322 b.Run("sync.Map", func(b *testing.B) { 323 var l sync.Map 324 for i := 0; i < initsize*rate; i++ { 325 if fastrand.Uint32n(rate) == 0 { 326 l.Store(strconv.Itoa(i), nil) 327 } 328 } 329 b.ResetTimer() 330 b.RunParallel(func(pb *testing.PB) { 331 for pb.Next() { 332 _, _ = l.Load(strconv.Itoa(int(fastrand.Uint32n(initsize * rate)))) 333 } 334 }) 335 }) 336 } 337 338 func BenchmarkString30Store70Load(b *testing.B) { 339 b.Run("skipmap", func(b *testing.B) { 340 l := New[string, any](bcomparator.StringComparator()) 341 b.ResetTimer() 342 b.RunParallel(func(pb *testing.PB) { 343 for pb.Next() { 344 u := fastrand.Uint32n(10) 345 if u < 3 { 346 l.Store(strconv.Itoa(int(fastrand.Uint32n(randN))), nil) 347 } else { 348 l.Load(strconv.Itoa(int(fastrand.Uint32n(randN)))) 349 } 350 } 351 }) 352 }) 353 b.Run("sync.Map", func(b *testing.B) { 354 var l sync.Map 355 b.ResetTimer() 356 b.RunParallel(func(pb *testing.PB) { 357 for pb.Next() { 358 u := fastrand.Uint32n(10) 359 if u < 3 { 360 l.Store(strconv.Itoa(int(fastrand.Uint32n(randN))), nil) 361 } else { 362 l.Load(strconv.Itoa(int(fastrand.Uint32n(randN)))) 363 } 364 } 365 }) 366 }) 367 } 368 369 func BenchmarkString1Delete9Store90Load(b *testing.B) { 370 b.Run("skipmap", func(b *testing.B) { 371 l := New[string, any](bcomparator.StringComparator()) 372 for i := 0; i < initsize; i++ { 373 l.Store(strconv.Itoa(i), nil) 374 } 375 b.ResetTimer() 376 b.RunParallel(func(pb *testing.PB) { 377 for pb.Next() { 378 u := fastrand.Uint32n(100) 379 if u < 9 { 380 l.Store(strconv.Itoa(int(fastrand.Uint32n(randN))), nil) 381 } else if u == 10 { 382 l.Delete(strconv.Itoa(int(fastrand.Uint32n(randN)))) 383 } else { 384 l.Load(strconv.Itoa(int(fastrand.Uint32n(randN)))) 385 } 386 } 387 }) 388 }) 389 b.Run("sync.Map", func(b *testing.B) { 390 var l sync.Map 391 for i := 0; i < initsize; i++ { 392 l.Store(strconv.Itoa(i), nil) 393 } 394 b.ResetTimer() 395 b.RunParallel(func(pb *testing.PB) { 396 for pb.Next() { 397 u := fastrand.Uint32n(100) 398 if u < 9 { 399 l.Store(strconv.Itoa(int(fastrand.Uint32n(randN))), nil) 400 } else if u == 10 { 401 l.Delete(strconv.Itoa(int(fastrand.Uint32n(randN)))) 402 } else { 403 l.Load(strconv.Itoa(int(fastrand.Uint32n(randN)))) 404 } 405 } 406 }) 407 }) 408 } 409 410 func BenchmarkString1Range9Delete90Store900Load(b *testing.B) { 411 b.Run("skipmap", func(b *testing.B) { 412 l := New[string, any](bcomparator.StringComparator()) 413 for i := 0; i < initsize; i++ { 414 l.Store(strconv.Itoa(i), nil) 415 } 416 b.ResetTimer() 417 b.RunParallel(func(pb *testing.PB) { 418 for pb.Next() { 419 u := fastrand.Uint32n(1000) 420 if u == 0 { 421 l.Range(func(key string, value interface{}) bool { 422 return true 423 }) 424 } else if u > 10 && u < 20 { 425 l.Delete(strconv.Itoa(int(fastrand.Uint32n(randN)))) 426 } else if u >= 100 && u < 190 { 427 l.Store(strconv.Itoa(int(fastrand.Uint32n(randN))), nil) 428 } else { 429 l.Load(strconv.Itoa(int(fastrand.Uint32n(randN)))) 430 } 431 } 432 }) 433 }) 434 b.Run("sync.Map", func(b *testing.B) { 435 var l sync.Map 436 for i := 0; i < initsize; i++ { 437 l.Store(strconv.Itoa(i), nil) 438 } 439 b.ResetTimer() 440 b.RunParallel(func(pb *testing.PB) { 441 for pb.Next() { 442 u := fastrand.Uint32n(1000) 443 if u == 0 { 444 l.Range(func(key, value interface{}) bool { 445 return true 446 }) 447 } else if u > 10 && u < 20 { 448 l.Delete(strconv.Itoa(int(fastrand.Uint32n(randN)))) 449 } else if u >= 100 && u < 190 { 450 l.Store(strconv.Itoa(int(fastrand.Uint32n(randN))), nil) 451 } else { 452 l.Load(strconv.Itoa(int(fastrand.Uint32n(randN)))) 453 } 454 } 455 }) 456 }) 457 }