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