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  }