github.com/cockroachdb/pebble@v1.1.1-0.20240513155919-3622ade60459/internal/randvar/skewed_latest.go (about) 1 // Copyright 2018 The Cockroach Authors. 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 12 // implied. See the License for the specific language governing 13 // permissions and limitations under the License. See the AUTHORS file 14 // for names of contributors. 15 16 package randvar 17 18 import ( 19 "sync" 20 21 "golang.org/x/exp/rand" 22 ) 23 24 // SkewedLatest is a random number generator that generates numbers in 25 // the range [min, max], but skews it towards max using a zipfian 26 // distribution. 27 type SkewedLatest struct { 28 mu struct { 29 sync.RWMutex 30 max uint64 31 zipf *Zipf 32 } 33 } 34 35 // NewDefaultSkewedLatest constructs a new SkewedLatest generator with the 36 // default parameters. 37 func NewDefaultSkewedLatest() (*SkewedLatest, error) { 38 return NewSkewedLatest(1, defaultMax, defaultTheta) 39 } 40 41 // NewSkewedLatest constructs a new SkewedLatest generator with the given 42 // parameters. It returns an error if the parameters are outside the accepted 43 // range. 44 func NewSkewedLatest(min, max uint64, theta float64) (*SkewedLatest, error) { 45 z := &SkewedLatest{} 46 z.mu.max = max 47 zipf, err := NewZipf(0, max-min, theta) 48 if err != nil { 49 return nil, err 50 } 51 z.mu.zipf = zipf 52 return z, nil 53 } 54 55 // IncMax increments max. 56 func (z *SkewedLatest) IncMax(delta int) { 57 z.mu.Lock() 58 z.mu.zipf.IncMax(delta) 59 z.mu.max += uint64(delta) 60 z.mu.Unlock() 61 } 62 63 // Max returns max. 64 func (z *SkewedLatest) Max() uint64 { 65 z.mu.Lock() 66 defer z.mu.Unlock() 67 return z.mu.zipf.Max() 68 } 69 70 // Uint64 returns a random Uint64 between min and max, where keys near max are 71 // most likely to be drawn. 72 func (z *SkewedLatest) Uint64(rng *rand.Rand) uint64 { 73 z.mu.RLock() 74 result := z.mu.max - z.mu.zipf.Uint64(rng) 75 z.mu.RUnlock() 76 return result 77 }