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  }