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