github.com/benz9527/xboot@v0.0.0-20240504061247-c23f15593274/lib/list/x_conc_skl_test.go (about)

     1  package list
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	randv2 "math/rand/v2"
     7  	"sort"
     8  	"sync"
     9  	"sync/atomic"
    10  	"testing"
    11  	"time"
    12  
    13  	"github.com/benz9527/xboot/lib/id"
    14  	"github.com/stretchr/testify/assert"
    15  	"github.com/stretchr/testify/require"
    16  )
    17  
    18  func TestXConcSkl_SerialProcessing(t *testing.T) {
    19  	opts := make([]SklOption[uint64, *xSklObject], 0, 2)
    20  	opts = append(opts, WithXConcSklDataNodeUniqueMode[uint64, *xSklObject](),
    21  		WithSklKeyCmpDesc[uint64, *xSklObject]())
    22  
    23  	skl, err := NewSkl[uint64, *xSklObject](
    24  		XConcSkl,
    25  		opts...,
    26  	)
    27  	require.NoError(t, err)
    28  
    29  	size := 5
    30  	for i := uint64(0); i < uint64(size); i++ {
    31  		for j := uint64(0); j < 10; j++ {
    32  			w := (i+1)*100 + j
    33  			_ = skl.Insert(w, &xSklObject{id: fmt.Sprintf("%d", w)})
    34  		}
    35  	}
    36  	t.Logf("nodeLen: %d, indexCount: %d\n", skl.Len(), skl.IndexCount())
    37  
    38  	obj, err := skl.LoadFirst(401)
    39  	require.NoError(t, err)
    40  	require.Equal(t, "401", obj.Val().id)
    41  
    42  	for i := uint64(0); i < uint64(size); i++ {
    43  		for j := uint64(0); j < 10; j++ {
    44  			w := (i+1)*100 + j
    45  			_, _ = skl.RemoveFirst(w)
    46  		}
    47  	}
    48  	require.Equal(t, int64(0), skl.Len())
    49  	require.Equal(t, uint64(0), skl.IndexCount())
    50  }
    51  
    52  func TestXConcSkl_DataRace(t *testing.T) {
    53  	opts := make([]SklOption[uint64, *xSklObject], 0, 2)
    54  	opts = append(opts, WithXConcSklDataNodeUniqueMode[uint64, *xSklObject]())
    55  
    56  	skl, err := NewSkl[uint64, *xSklObject](
    57  		XConcSkl,
    58  		opts...,
    59  	)
    60  	require.NoError(t, err)
    61  
    62  	ele, err := skl.PopHead()
    63  	require.Nil(t, ele)
    64  	require.True(t, errors.Is(err, ErrXSklIsEmpty))
    65  
    66  	size := 5
    67  	size2 := 10
    68  	var wg sync.WaitGroup
    69  	wg.Add(size * size2)
    70  	for i := uint64(0); i < uint64(size); i++ {
    71  		for j := uint64(0); j < uint64(size2); j++ {
    72  			go func(idx uint64) {
    73  				w := idx
    74  				time.Sleep(time.Duration(cryptoRandUint32()%5) * time.Millisecond)
    75  				_ = skl.Insert(w, &xSklObject{id: fmt.Sprintf("%d", w)})
    76  				wg.Done()
    77  			}((i+1)*100 + j)
    78  		}
    79  	}
    80  	wg.Wait()
    81  	t.Logf("nodeLen: %d, indexCount: %d\n", skl.Len(), skl.IndexCount())
    82  
    83  	obj, err := skl.LoadFirst(401)
    84  	require.NoError(t, err)
    85  	require.Equal(t, "401", obj.Val().id)
    86  
    87  	wg.Add(size * size2)
    88  	for i := uint64(0); i < uint64(size); i++ {
    89  		for j := uint64(0); j < uint64(size2); j++ {
    90  			go func(idx uint64) {
    91  				w := idx
    92  				time.Sleep(time.Duration(cryptoRandUint32()%5) * time.Millisecond)
    93  				_, _ = skl.RemoveFirst(w)
    94  				wg.Done()
    95  			}((i+1)*100 + j)
    96  		}
    97  	}
    98  	wg.Wait()
    99  	require.Equal(t, int64(0), skl.Len())
   100  	require.Equal(t, uint64(0), skl.IndexCount())
   101  }
   102  
   103  func TestXConcSkl_LinkedList_SerialProcessing(t *testing.T) {
   104  	skl := &xConcSkl[uint64, *xSklObject]{
   105  		head:    newXConcSklHead[uint64, *xSklObject](),
   106  		levels:  1,
   107  		nodeLen: 0,
   108  		vcmp: func(i, j *xSklObject) int64 {
   109  			// avoid calculation overflow
   110  			_i, _j := i.Hash(), j.Hash()
   111  			if _i == _j {
   112  				return 0
   113  			} else if _i > _j {
   114  				return 1
   115  			}
   116  			return -1
   117  		},
   118  		rand:  randomLevelV3,
   119  		flags: 0,
   120  	}
   121  	idGen, _ := id.MonotonicNonZeroID()
   122  	skl.optVer = idGen
   123  	skl.flags = setBitsAs(skl.flags, xConcSklXNodeModeFlagBits, uint32(linkedList))
   124  
   125  	ele, err := skl.PopHead()
   126  	require.Nil(t, ele)
   127  	require.True(t, errors.Is(err, ErrXSklIsEmpty))
   128  
   129  	skl.Insert(4, &xSklObject{id: fmt.Sprintf("%d", 9)})
   130  	skl.Insert(4, &xSklObject{id: fmt.Sprintf("%d", 5)})
   131  	skl.Insert(4, &xSklObject{id: fmt.Sprintf("%d", 8)})
   132  	skl.Insert(4, &xSklObject{id: fmt.Sprintf("%d", 7)})
   133  	skl.Insert(4, &xSklObject{id: fmt.Sprintf("%d", 1)})
   134  	skl.Insert(4, &xSklObject{id: fmt.Sprintf("%d", 2)})
   135  	skl.Insert(4, &xSklObject{id: fmt.Sprintf("%d", 4)})
   136  	skl.Insert(4, &xSklObject{id: fmt.Sprintf("%d", 6)})
   137  	skl.Insert(2, &xSklObject{id: fmt.Sprintf("%d", 9)})
   138  	skl.Insert(2, &xSklObject{id: fmt.Sprintf("%d", 5)})
   139  	skl.Insert(2, &xSklObject{id: fmt.Sprintf("%d", 8)})
   140  	skl.Insert(2, &xSklObject{id: fmt.Sprintf("%d", 7)})
   141  	skl.Insert(2, &xSklObject{id: fmt.Sprintf("%d", 1)})
   142  	skl.Insert(2, &xSklObject{id: fmt.Sprintf("%d", 2)})
   143  	skl.Insert(2, &xSklObject{id: fmt.Sprintf("%d", 4)})
   144  	skl.Insert(2, &xSklObject{id: fmt.Sprintf("%d", 6)})
   145  	skl.Insert(3, &xSklObject{id: fmt.Sprintf("%d", 100)})
   146  	skl.Insert(3, &xSklObject{id: fmt.Sprintf("%d", 200)})
   147  	skl.Insert(3, &xSklObject{id: fmt.Sprintf("%d", 2)})
   148  	skl.Insert(1, &xSklObject{id: fmt.Sprintf("%d", 9)})
   149  	skl.Insert(1, &xSklObject{id: fmt.Sprintf("%d", 200)})
   150  	skl.Insert(1, &xSklObject{id: fmt.Sprintf("%d", 2)})
   151  
   152  	t.Logf("nodeLen: %d, indexCount: %d\n", skl.Len(), skl.IndexCount())
   153  
   154  	skl.Foreach(func(idx int64, item SklIterationItem[uint64, *xSklObject]) bool {
   155  		t.Logf("idx: %d, key: %v, value: %v, levels: %d, count: %d\n", idx, item.Key(), item.Val(), item.NodeLevel(), item.NodeItemCount())
   156  		return true
   157  	})
   158  
   159  	aux := make(xConcSklAux[uint64, *xSklObject], 2*sklMaxLevel)
   160  	foundResult := skl.rmTraverse(1, false, aux)
   161  	assert.LessOrEqual(t, int32(0), foundResult)
   162  	require.True(t, isSet(aux.loadPred(0).flags, nodeIsHeadFlagBit))
   163  	require.Equal(t, uint64(1), aux.loadSucc(0).key)
   164  	require.Equal(t, "9", (*aux.loadSucc(0).atomicLoadRoot().linkedListNext().vptr).id)
   165  
   166  	foundResult = skl.rmTraverse(2, false, aux)
   167  	assert.LessOrEqual(t, int32(0), foundResult)
   168  	require.Equal(t, uint64(1), aux.loadPred(0).key)
   169  	require.Equal(t, "9", (*aux.loadPred(0).atomicLoadRoot().linkedListNext().vptr).id)
   170  	require.Equal(t, uint64(2), aux.loadSucc(0).key)
   171  	require.Equal(t, "9", (*aux.loadSucc(0).atomicLoadRoot().linkedListNext().vptr).id)
   172  
   173  	foundResult = skl.rmTraverse(3, false, aux)
   174  	assert.LessOrEqual(t, int32(0), foundResult)
   175  	require.Equal(t, uint64(2), aux.loadPred(0).key)
   176  	require.Equal(t, "9", (*aux.loadPred(0).atomicLoadRoot().linkedListNext().vptr).id)
   177  	require.Equal(t, uint64(3), aux.loadSucc(0).key)
   178  	require.Equal(t, "2", (*aux.loadSucc(0).atomicLoadRoot().linkedListNext().vptr).id)
   179  
   180  	foundResult = skl.rmTraverse(4, false, aux)
   181  	assert.LessOrEqual(t, int32(0), foundResult)
   182  	require.Equal(t, uint64(3), aux.loadPred(0).key)
   183  	require.Equal(t, "2", (*aux.loadPred(0).atomicLoadRoot().linkedListNext().vptr).id)
   184  	require.Equal(t, uint64(4), aux.loadSucc(0).key)
   185  	require.Equal(t, "9", (*aux.loadSucc(0).atomicLoadRoot().linkedListNext().vptr).id)
   186  
   187  	foundResult = skl.rmTraverse(100, false, aux)
   188  	assert.Equal(t, int32(-1), foundResult)
   189  
   190  	foundResult = skl.rmTraverse(0, false, aux)
   191  	assert.Equal(t, int32(-1), foundResult)
   192  
   193  	removed, err := skl.RemoveAll(3)
   194  	require.NoError(t, err)
   195  	require.Equal(t, uint64(3), removed[0].Key())
   196  	require.Equal(t, "2", removed[0].Val().id)
   197  	require.Equal(t, uint64(3), removed[1].Key())
   198  	require.Equal(t, "200", removed[1].Val().id)
   199  	require.Equal(t, uint64(3), removed[2].Key())
   200  	require.Equal(t, "100", removed[2].Val().id)
   201  	skl.Foreach(func(idx int64, item SklIterationItem[uint64, *xSklObject]) bool {
   202  		if item.Key() == uint64(3) {
   203  			t.FailNow()
   204  			return false
   205  		}
   206  		return true
   207  	})
   208  
   209  	removed, err = skl.RemoveIfMatch(2, func(that *xSklObject) bool {
   210  		return that.id == "8"
   211  	})
   212  	require.NoError(t, err)
   213  	require.Equal(t, 1, len(removed))
   214  	require.Equal(t, uint64(2), removed[0].Key())
   215  	require.Equal(t, "8", removed[0].Val().id)
   216  	skl.Foreach(func(idx int64, item SklIterationItem[uint64, *xSklObject]) bool {
   217  		if item.Key() == uint64(2) && item.Val().id == "8" {
   218  			t.FailNow()
   219  			return false
   220  		}
   221  		return true
   222  	})
   223  
   224  	loaded, err := skl.LoadAll(1)
   225  	require.NoError(t, err)
   226  	require.Equal(t, 3, len(loaded))
   227  	require.Equal(t, uint64(1), loaded[0].Key())
   228  	require.Equal(t, "9", loaded[0].Val().id)
   229  	require.Equal(t, uint64(1), loaded[1].Key())
   230  	require.Equal(t, "2", loaded[1].Val().id)
   231  	require.Equal(t, uint64(1), loaded[2].Key())
   232  	require.Equal(t, "200", loaded[2].Val().id)
   233  
   234  	loaded, err = skl.LoadIfMatch(2, func(that *xSklObject) bool {
   235  		return that.id == "9"
   236  	})
   237  	require.NoError(t, err)
   238  	require.Equal(t, 1, len(loaded))
   239  	require.Equal(t, uint64(2), loaded[0].Key())
   240  	require.Equal(t, "9", loaded[0].Val().id)
   241  }
   242  
   243  func TestXConcSkl_Rbtree_SerialProcessing(t *testing.T) {
   244  	skl := &xConcSkl[uint64, *xSklObject]{
   245  		head:    newXConcSklHead[uint64, *xSklObject](),
   246  		levels:  1,
   247  		nodeLen: 0,
   248  		vcmp: func(i, j *xSklObject) int64 {
   249  			// avoid calculation overflow
   250  			_i, _j := i.Hash(), j.Hash()
   251  			if _i == _j {
   252  				return 0
   253  			} else if _i > _j {
   254  				return 1
   255  			}
   256  			return -1
   257  		},
   258  		rand:  randomLevelV3,
   259  		flags: 0,
   260  	}
   261  	idGen, _ := id.MonotonicNonZeroID()
   262  	skl.optVer = idGen
   263  	skl.flags = setBitsAs(skl.flags, xConcSklXNodeModeFlagBits, uint32(rbtree))
   264  
   265  	ele, err := skl.PopHead()
   266  	require.Nil(t, ele)
   267  	require.True(t, errors.Is(err, ErrXSklIsEmpty))
   268  
   269  	skl.Insert(4, &xSklObject{id: fmt.Sprintf("%d", 9)})
   270  	skl.Insert(4, &xSklObject{id: fmt.Sprintf("%d", 5)})
   271  	skl.Insert(4, &xSklObject{id: fmt.Sprintf("%d", 8)})
   272  	skl.Insert(4, &xSklObject{id: fmt.Sprintf("%d", 7)})
   273  	skl.Insert(4, &xSklObject{id: fmt.Sprintf("%d", 1)})
   274  	skl.Insert(4, &xSklObject{id: fmt.Sprintf("%d", 2)})
   275  	skl.Insert(4, &xSklObject{id: fmt.Sprintf("%d", 4)})
   276  	skl.Insert(4, &xSklObject{id: fmt.Sprintf("%d", 6)})
   277  	skl.Insert(2, &xSklObject{id: fmt.Sprintf("%d", 9)})
   278  	skl.Insert(2, &xSklObject{id: fmt.Sprintf("%d", 5)})
   279  	skl.Insert(2, &xSklObject{id: fmt.Sprintf("%d", 8)})
   280  	skl.Insert(2, &xSklObject{id: fmt.Sprintf("%d", 7)})
   281  	skl.Insert(2, &xSklObject{id: fmt.Sprintf("%d", 1)})
   282  	skl.Insert(2, &xSklObject{id: fmt.Sprintf("%d", 2)})
   283  	skl.Insert(2, &xSklObject{id: fmt.Sprintf("%d", 4)})
   284  	skl.Insert(2, &xSklObject{id: fmt.Sprintf("%d", 6)})
   285  	skl.Insert(3, &xSklObject{id: fmt.Sprintf("%d", 100)})
   286  	skl.Insert(3, &xSklObject{id: fmt.Sprintf("%d", 200)})
   287  	skl.Insert(3, &xSklObject{id: fmt.Sprintf("%d", 2)})
   288  	skl.Insert(1, &xSklObject{id: fmt.Sprintf("%d", 9)})
   289  	skl.Insert(1, &xSklObject{id: fmt.Sprintf("%d", 200)})
   290  	skl.Insert(1, &xSklObject{id: fmt.Sprintf("%d", 2)})
   291  
   292  	t.Logf("nodeLen: %d, indexCount: %d\n", skl.Len(), skl.IndexCount())
   293  
   294  	skl.Foreach(func(idx int64, item SklIterationItem[uint64, *xSklObject]) bool {
   295  		t.Logf("idx: %d, key: %v, value: %v, levels: %d, count: %d\n", idx, item.Key(), item.Val(), item.NodeLevel(), item.NodeItemCount())
   296  		return true
   297  	})
   298  
   299  	removed, err := skl.RemoveAll(3)
   300  	require.NoError(t, err)
   301  	require.Equal(t, uint64(3), removed[0].Key())
   302  	require.Equal(t, "2", removed[0].Val().id)
   303  	require.Equal(t, uint64(3), removed[1].Key())
   304  	require.Equal(t, "200", removed[1].Val().id)
   305  	require.Equal(t, uint64(3), removed[2].Key())
   306  	require.Equal(t, "100", removed[2].Val().id)
   307  	skl.Foreach(func(idx int64, item SklIterationItem[uint64, *xSklObject]) bool {
   308  		if item.Key() == uint64(3) {
   309  			t.FailNow()
   310  			return false
   311  		}
   312  		return true
   313  	})
   314  
   315  	removed, err = skl.RemoveIfMatch(2, func(that *xSklObject) bool {
   316  		return that.id == "8"
   317  	})
   318  	require.NoError(t, err)
   319  	require.Equal(t, 1, len(removed))
   320  	require.Equal(t, uint64(2), removed[0].Key())
   321  	require.Equal(t, "8", removed[0].Val().id)
   322  	skl.Foreach(func(idx int64, item SklIterationItem[uint64, *xSklObject]) bool {
   323  		if item.Key() == uint64(2) && item.Val().id == "8" {
   324  			t.FailNow()
   325  			return false
   326  		}
   327  		return true
   328  	})
   329  
   330  	loaded, err := skl.LoadAll(1)
   331  	require.NoError(t, err)
   332  	require.Equal(t, 3, len(loaded))
   333  	require.Equal(t, uint64(1), loaded[0].Key())
   334  	require.Equal(t, "9", loaded[0].Val().id)
   335  	require.Equal(t, uint64(1), loaded[1].Key())
   336  	require.Equal(t, "2", loaded[1].Val().id)
   337  	require.Equal(t, uint64(1), loaded[2].Key())
   338  	require.Equal(t, "200", loaded[2].Val().id)
   339  
   340  	loaded, err = skl.LoadIfMatch(2, func(that *xSklObject) bool {
   341  		return that.id == "9"
   342  	})
   343  	require.NoError(t, err)
   344  	require.Equal(t, 1, len(loaded))
   345  	require.Equal(t, uint64(2), loaded[0].Key())
   346  	require.Equal(t, "9", loaded[0].Val().id)
   347  }
   348  
   349  func xConcSklDuplicateDataRaceRunCore(t *testing.T, mode xNodeMode, rmBySucc bool) {
   350  	opts := []SklOption[uint64, int64]{
   351  		WithSklRandLevelGen[uint64, int64](randomLevelV3),
   352  	}
   353  	switch mode {
   354  	case linkedList:
   355  		opts = append(opts, WithXConcSklDataNodeLinkedListMode[uint64, int64](
   356  			func(i, j int64) int64 {
   357  				// avoid calculation overflow
   358  				if i == j {
   359  					return 0
   360  				} else if i > j {
   361  					return 1
   362  				}
   363  				return -1
   364  			}))
   365  	case rbtree:
   366  		opts = append(opts, WithXConcSklDataNodeRbtreeMode[uint64, int64](
   367  			func(i, j int64) int64 {
   368  				// avoid calculation overflow
   369  				if i == j {
   370  					return 0
   371  				} else if i > j {
   372  					return 1
   373  				}
   374  				return -1
   375  			}, rmBySucc))
   376  	}
   377  
   378  	skl, err := NewXSkl[uint64, int64](
   379  		XConcSkl,
   380  		opts...,
   381  	)
   382  	require.NoError(t, err)
   383  
   384  	ele, err := skl.PopHead()
   385  	require.Nil(t, ele)
   386  	require.True(t, errors.Is(err, ErrXSklIsEmpty))
   387  
   388  	size := 10
   389  	size2 := 10
   390  	unorderedWeights := make([]int64, 0, size2)
   391  	for i := 0; i < size2; i++ {
   392  		unorderedWeights = append(unorderedWeights, int64(cryptoRandUint64()))
   393  	}
   394  	orderedWeights := make([]int64, 0, size2)
   395  	orderedWeights = append(orderedWeights, unorderedWeights...)
   396  	sort.Slice(orderedWeights, func(i, j int) bool {
   397  		return orderedWeights[i] < orderedWeights[j]
   398  	})
   399  
   400  	var wg sync.WaitGroup
   401  	wg.Add(size * size2)
   402  
   403  	type answer struct {
   404  		w  uint64
   405  		id int64
   406  	}
   407  	expected := make([]*answer, 0, size*size2)
   408  
   409  	for i := uint64(0); i < uint64(size); i++ {
   410  		for j := uint64(0); j < uint64(size2); j++ {
   411  			go func(_i, _j uint64) {
   412  				w := (_i + 1) * 100
   413  				time.Sleep(time.Duration(cryptoRandUint32()%5) * time.Millisecond)
   414  				_ = skl.Insert(w, unorderedWeights[_j])
   415  				wg.Done()
   416  			}(i, j)
   417  			expected = append(expected, &answer{w: (i + 1) * 100, id: orderedWeights[j]})
   418  		}
   419  	}
   420  	wg.Wait()
   421  	t.Logf("nodeLen: %d, indexCount: %d\n", skl.Len(), skl.IndexCount())
   422  
   423  	skl.Foreach(func(idx int64, item SklIterationItem[uint64, int64]) bool {
   424  		require.Equalf(t, expected[idx].w, item.Key(), "exp: %d; actual: %d\n", expected[idx].w, item.Key())
   425  		require.Equalf(t, expected[idx].id, item.Val(), "exp: %d; actual: %d\n", expected[idx].id, item.Val())
   426  		return true
   427  	})
   428  
   429  	wg.Add(size * size2)
   430  	for i := uint64(0); i < uint64(size); i++ {
   431  		for j := uint64(0); j < uint64(size2); j++ {
   432  			go func(_i, _j uint64) {
   433  				w := (_i + 1) * 100
   434  				time.Sleep(time.Duration(cryptoRandUint32()%5) * time.Millisecond)
   435  				if _, err := skl.RemoveFirst(w); err != nil {
   436  					t.Logf("remove failed, key: %d, err: %v\n", w, err)
   437  				}
   438  				wg.Done()
   439  			}(i, j)
   440  		}
   441  	}
   442  	wg.Wait()
   443  	require.Equal(t, int64(0), skl.Len())
   444  	require.Equal(t, uint64(0), skl.IndexCount())
   445  }
   446  
   447  func TestXConcSkl_Duplicate_DataRace(t *testing.T) {
   448  	type testcase struct {
   449  		name       string
   450  		typ        xNodeMode
   451  		rbRmBySucc bool
   452  	}
   453  	testcases := []testcase{
   454  		{
   455  			name: "skl lock free mutex data race - linkedlist",
   456  			typ:  linkedList,
   457  		},
   458  		{
   459  			name: "skl lock free mutex data race - rbtree",
   460  			typ:  rbtree,
   461  		},
   462  		{
   463  			name:       "skl lock free mutex data race - rbtree (succ)",
   464  			typ:        rbtree,
   465  			rbRmBySucc: true,
   466  		},
   467  	}
   468  	t.Parallel()
   469  	for _, tc := range testcases {
   470  		t.Run(tc.name, func(tt *testing.T) {
   471  			xConcSklDuplicateDataRaceRunCore(tt, tc.typ, tc.rbRmBySucc)
   472  		})
   473  	}
   474  }
   475  
   476  func xConcSklPeekAndPopHeadRunCore(t *testing.T, mode xNodeMode) {
   477  	skl := &xConcSkl[uint64, int64]{
   478  		head:    newXConcSklHead[uint64, int64](),
   479  		levels:  1,
   480  		nodeLen: 0,
   481  		vcmp: func(i, j int64) int64 {
   482  			// avoid calculation overflow
   483  			if i == j {
   484  				return 0
   485  			} else if i > j {
   486  				return 1
   487  			}
   488  			return -1
   489  		},
   490  		rand:  randomLevelV3,
   491  		flags: 0,
   492  	}
   493  	idGen, _ := id.MonotonicNonZeroID()
   494  	skl.optVer = idGen
   495  	if mode != unique {
   496  		skl.flags = setBitsAs(skl.flags, xConcSklXNodeModeFlagBits, uint32(mode))
   497  	}
   498  
   499  	ele, err := skl.PopHead()
   500  	require.Nil(t, ele)
   501  	require.True(t, errors.Is(err, ErrXSklIsEmpty))
   502  
   503  	size := 10
   504  	size2 := 10
   505  	unorderedWeights := make([]int64, 0, size2)
   506  	for i := 0; i < size2; i++ {
   507  		unorderedWeights = append(unorderedWeights, int64(cryptoRandUint64()))
   508  	}
   509  	orderedWeights := make([]int64, 0, size2)
   510  	orderedWeights = append(orderedWeights, unorderedWeights...)
   511  	sort.Slice(orderedWeights, func(i, j int) bool {
   512  		return orderedWeights[i] < orderedWeights[j]
   513  	})
   514  
   515  	type answer struct {
   516  		w  uint64
   517  		id int64
   518  	}
   519  	expected := make([]*answer, 0, size*size2)
   520  
   521  	for i := uint64(0); i < uint64(size); i++ {
   522  		for j := uint64(0); j < uint64(size2); j++ {
   523  			w := (i + 1) * 100
   524  			_ = skl.Insert(w, orderedWeights[j])
   525  			expected = append(expected, &answer{w: (i + 1) * 100, id: orderedWeights[j]})
   526  		}
   527  	}
   528  	t.Logf("nodeLen: %d, indexCount: %d\n", skl.Len(), skl.IndexCount())
   529  
   530  	if mode == unique {
   531  		skl.Foreach(func(idx int64, item SklIterationItem[uint64, int64]) bool {
   532  			require.Equalf(t, expected[idx*int64(size2)+9].w, item.Key(), "idx: %d; exp: %d; actual: %d\n", idx, expected[idx*int64(size2)+9].w, item.Key())
   533  			require.Equalf(t, expected[idx*int64(size2)+9].id, item.Val(), "idx: %d; exp: %d; actual: %d\n", idx, expected[idx*int64(size2)+9].id, item.Val())
   534  			return true
   535  		})
   536  	} else {
   537  		skl.Foreach(func(idx int64, item SklIterationItem[uint64, int64]) bool {
   538  			require.Equalf(t, expected[idx].w, item.Key(), "exp: %d; actual: %d\n", expected[idx].w, item.Key())
   539  			require.Equalf(t, expected[idx].id, item.Val(), "exp: %d; actual: %d\n", expected[idx].id, item.Val())
   540  			return true
   541  		})
   542  	}
   543  
   544  	for i := int64(0); skl.Len() > 0; i++ {
   545  		h1 := skl.PeekHead()
   546  		require.NotNil(t, h1)
   547  		h2, err := skl.PopHead()
   548  		require.NoError(t, err)
   549  		require.NotNil(t, h2)
   550  		if mode == unique {
   551  			require.Equal(t, expected[i*int64(size2)+9].w, h1.Key())
   552  			require.Equal(t, expected[i*int64(size2)+9].id, h1.Val())
   553  		} else {
   554  			require.Equal(t, expected[i].w, h1.Key())
   555  			require.Equal(t, expected[i].id, h1.Val())
   556  		}
   557  		require.Equal(t, h1.Key(), h2.Key())
   558  		require.Equal(t, h1.Val(), h2.Val())
   559  	}
   560  }
   561  
   562  func TestXConcSklPeekAndPopHead(t *testing.T) {
   563  	type testcase struct {
   564  		name string
   565  		typ  xNodeMode
   566  	}
   567  	testcases := []testcase{
   568  		{
   569  			name: "skl lock free mutex data race - unique",
   570  			typ:  unique,
   571  		},
   572  		{
   573  			name: "skl lock free mutex data race - linkedlist",
   574  			typ:  linkedList,
   575  		},
   576  
   577  		{
   578  			name: "skl lock free mutex data race - rbtree",
   579  			typ:  rbtree,
   580  		},
   581  		{
   582  			name: "skl lock free mutex data race - rbtree (succ)",
   583  			typ:  rbtree,
   584  		},
   585  	}
   586  	t.Parallel()
   587  	for _, tc := range testcases {
   588  		t.Run(tc.name, func(tt *testing.T) {
   589  			xConcSklPeekAndPopHeadRunCore(tt, tc.typ)
   590  		})
   591  	}
   592  }
   593  
   594  func BenchmarkXConcSklUnique_Random(b *testing.B) {
   595  	testByBytes := []byte(`abc`)
   596  
   597  	b.StopTimer()
   598  	opts := make([]SklOption[int, []byte], 0, 2)
   599  	opts = append(opts, WithXConcSklDataNodeUniqueMode[int, []byte]())
   600  	skl, err := NewSkl[int, []byte](
   601  		XConcSkl,
   602  		opts...,
   603  	)
   604  	if err != nil {
   605  		panic(err)
   606  	}
   607  
   608  	rngArr := make([]int, 0, b.N)
   609  	for i := 0; i < b.N; i++ {
   610  		rngArr = append(rngArr, randv2.Int())
   611  	}
   612  
   613  	b.StartTimer()
   614  	for i := 0; i < b.N; i++ {
   615  		err := skl.Insert(rngArr[i], testByBytes)
   616  		if err != nil {
   617  			panic(err)
   618  		}
   619  	}
   620  }
   621  
   622  func BenchmarkXConcSklUnique_Serial(b *testing.B) {
   623  	testByBytes := []byte(`abc`)
   624  
   625  	b.StopTimer()
   626  	opts := make([]SklOption[int, []byte], 0, 2)
   627  	opts = append(opts, WithXConcSklDataNodeUniqueMode[int, []byte]())
   628  	skl, err := NewSkl[int, []byte](
   629  		XConcSkl,
   630  		opts...,
   631  	)
   632  	if err != nil {
   633  		panic(err)
   634  	}
   635  
   636  	b.StartTimer()
   637  	for i := 0; i < b.N; i++ {
   638  		skl.Insert(i, testByBytes)
   639  	}
   640  }
   641  
   642  func TestXConcSklUnique(t *testing.T) {
   643  	testByBytes := []byte(`abc`)
   644  
   645  	opts := make([]SklOption[int, []byte], 0, 2)
   646  	opts = append(opts, WithXConcSklDataNodeUniqueMode[int, []byte]())
   647  	skl, err := NewSkl[int, []byte](
   648  		XConcSkl,
   649  		opts...,
   650  	)
   651  	if err != nil {
   652  		panic(err)
   653  	}
   654  
   655  	for i := 0; i < 3000000; i++ {
   656  		skl.Insert(i, testByBytes)
   657  	}
   658  }
   659  
   660  func BenchmarkXSklReadWrite(b *testing.B) {
   661  	value := []byte(`abc`)
   662  	for i := 0; i <= 10; i++ {
   663  		b.Run(fmt.Sprintf("frac_%d", i), func(b *testing.B) {
   664  			readFrac := float32(i) / 10.0
   665  			opts := make([]SklOption[int, []byte], 0, 2)
   666  			opts = append(opts, WithXConcSklDataNodeUniqueMode[int, []byte]())
   667  			skl, err := NewSkl[int, []byte](
   668  				XConcSkl,
   669  				opts...,
   670  			)
   671  			if err != nil {
   672  				panic(err)
   673  			}
   674  			b.ResetTimer()
   675  			count := atomic.Int64{}
   676  			b.RunParallel(func(pb *testing.PB) {
   677  				for pb.Next() {
   678  					if randv2.Float32() < readFrac {
   679  						v, err := skl.LoadFirst(randv2.Int())
   680  						if err != nil && v != nil {
   681  							count.Add(1)
   682  						}
   683  					} else {
   684  						skl.Insert(randv2.Int(), value)
   685  					}
   686  				}
   687  			})
   688  		})
   689  	}
   690  }