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  }