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

     1  package list
     2  
     3  import (
     4  	"math"
     5  	"math/bits"
     6  	"math/rand"
     7  	"sync"
     8  	"testing"
     9  
    10  	"github.com/stretchr/testify/assert"
    11  )
    12  
    13  func randomLevelV1(maxLevel int, currentElements int32) int32 {
    14  	// Call function maxLevels to get total?
    15  	// maxLevel => n, 2^n -1, there will be 2^n-1 elements in the skip list
    16  	var total uint64
    17  	if maxLevel == sklMaxLevel {
    18  		total = uint64(math.MaxUint32)
    19  	} else {
    20  		total = uint64(1)<<maxLevel - 1
    21  	}
    22  	// golang math random (math.Float64()) contains global mutex lock
    23  	// Ref
    24  	// https://cs.opensource.google/go/go/+/refs/tags/go1.21.5:src/math/rand/rand.go
    25  	// https://cs.opensource.google/go/go/+/refs/tags/go1.21.5:src/math/bits/bits.go
    26  	// 1. Avoid to use global mutex lock
    27  	// 2. Avoid to generate random number each time
    28  	rest := rand.Uint64() & total
    29  	// Bits right shift equal to manipulate a high-level bit
    30  	// Calculate the minimum bits of the random number
    31  	tmp := bits.Len64(rest) // Lookup table.
    32  	level := maxLevel - tmp + 1
    33  	// Avoid the value of randomly generated level deviates
    34  	//   far from the number of elements within the skip-list.
    35  	// level should be greater than but approximate to log(currentElements)
    36  	for level > 1 && uint64(1)<<(level-1) > uint64(currentElements) {
    37  		level--
    38  	}
    39  	return int32(level)
    40  }
    41  
    42  func TestMaxLevel(t *testing.T) {
    43  	levels := maxLevels(math.MaxInt32, 0.25) // 30
    44  	assert.GreaterOrEqual(t, 32, levels)
    45  
    46  	levels = maxLevels(int64(1), 0.25) // 0
    47  	assert.GreaterOrEqual(t, 0, levels)
    48  
    49  	levels = maxLevels(int64(2), 0.25) // 1
    50  	assert.GreaterOrEqual(t, 1, levels)
    51  }
    52  
    53  func TestRandomLevel(t *testing.T) {
    54  	loop := 10
    55  	for i := 0; i < loop; i++ {
    56  		t.Log(randomLevel(sklMaxLevel, int32(i)))
    57  	}
    58  }
    59  
    60  func TestRandomLevelV1(t *testing.T) {
    61  	var wg sync.WaitGroup
    62  	wg.Add(10)
    63  	for i := 0; i < 10; i++ {
    64  		go func(id int) {
    65  			loop := 1000
    66  			for j := 0; j < loop; j++ {
    67  				t.Logf("randv1 id: %d; rand: %d\n", id, randomLevelV1(sklMaxLevel, int32(j)))
    68  			}
    69  			wg.Done()
    70  		}(i)
    71  	}
    72  	wg.Wait()
    73  }
    74  
    75  func TestRandomLevelV2(t *testing.T) {
    76  	var wg sync.WaitGroup
    77  	wg.Add(10)
    78  	for i := 0; i < 10; i++ {
    79  		go func(id int) {
    80  			loop := 1000
    81  			for j := 0; j < loop; j++ {
    82  				t.Logf("randv2 id: %d; rand: %d\n", id, randomLevelV2(sklMaxLevel, int64(j)))
    83  			}
    84  			wg.Done()
    85  		}(i)
    86  	}
    87  	wg.Wait()
    88  }
    89  
    90  func TestRandomLevelV3(t *testing.T) {
    91  	var wg sync.WaitGroup
    92  	wg.Add(10)
    93  	for i := 0; i < 10; i++ {
    94  		go func(id int) {
    95  			loop := 1000
    96  			for j := 0; j < loop; j++ {
    97  				t.Logf("randv3 id: %d; rand: %d\n", id, randomLevelV3(sklMaxLevel, int64(j)))
    98  			}
    99  			wg.Done()
   100  		}(i)
   101  	}
   102  	wg.Wait()
   103  }
   104  
   105  func BenchmarkRandomLevel(b *testing.B) {
   106  	for i := 0; i < b.N; i++ {
   107  		randomLevel(sklMaxLevel, int32(i))
   108  	}
   109  	b.ReportAllocs()
   110  }
   111  
   112  func BenchmarkRandomLevelV2(b *testing.B) {
   113  	for i := 0; i < b.N; i++ {
   114  		randomLevelV2(sklMaxLevel, int64(i))
   115  	}
   116  	b.ReportAllocs()
   117  }