github.com/cockroachdb/pebble@v0.0.0-20231214172447-ab4952c5f87b/internal/fastrand/fastrand_test.go (about)

     1  // Copyright 2020 The LevelDB-Go and Pebble Authors. All rights reserved. Use
     2  // of this source code is governed by a BSD-style license that can be found in
     3  // the LICENSE file.
     4  
     5  package fastrand
     6  
     7  import (
     8  	"fmt"
     9  	"sync"
    10  	"testing"
    11  	"time"
    12  
    13  	"golang.org/x/exp/rand"
    14  )
    15  
    16  type defaultRand struct {
    17  	mu  sync.Mutex
    18  	src rand.PCGSource
    19  }
    20  
    21  func newDefaultRand() *defaultRand {
    22  	r := &defaultRand{}
    23  	r.src.Seed(uint64(time.Now().UnixNano()))
    24  	return r
    25  }
    26  
    27  func (r *defaultRand) Uint32() uint32 {
    28  	r.mu.Lock()
    29  	i := uint32(r.src.Uint64())
    30  	r.mu.Unlock()
    31  	return i
    32  }
    33  
    34  func BenchmarkFastRand(b *testing.B) {
    35  	b.RunParallel(func(pb *testing.PB) {
    36  		for pb.Next() {
    37  			Uint32()
    38  		}
    39  	})
    40  }
    41  
    42  func BenchmarkDefaultRand(b *testing.B) {
    43  	r := newDefaultRand()
    44  	b.RunParallel(func(pb *testing.PB) {
    45  		for pb.Next() {
    46  			r.Uint32()
    47  		}
    48  	})
    49  }
    50  
    51  // Benchmarks for single-threaded (ST) use of fastrand compared to
    52  // constructing a Rand, which can have heap allocation overhead.
    53  
    54  // Global state to disable elision of benchmark code.
    55  var xg uint32
    56  
    57  func BenchmarkSTFastRand(b *testing.B) {
    58  	var x uint32
    59  	for i := 0; i < b.N; i++ {
    60  		// Arbitrary constant.
    61  		x = Uint32n(2097152)
    62  	}
    63  	xg = x
    64  }
    65  
    66  func BenchmarkSTDefaultRand(b *testing.B) {
    67  	for _, newPeriod := range []int{0, 10, 100, 1000} {
    68  		name := "no-new"
    69  		if newPeriod > 0 {
    70  			name = fmt.Sprintf("new-period=%d", newPeriod)
    71  		}
    72  		b.Run(name, func(b *testing.B) {
    73  			r := rand.New(rand.NewSource(uint64(time.Now().UnixNano())))
    74  			b.ResetTimer()
    75  			var x uint32
    76  			for i := 0; i < b.N; i++ {
    77  				if newPeriod > 0 && i%newPeriod == 0 {
    78  					r = rand.New(rand.NewSource(uint64(time.Now().UnixNano())))
    79  				}
    80  				// Arbitrary constant.
    81  				x = uint32(r.Uint64n(2097152))
    82  			}
    83  			xg = x
    84  		})
    85  	}
    86  }