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