github.com/MetalBlockchain/metalgo@v1.11.9/utils/sampler/uniform_best.go (about) 1 // Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. 2 // See the file LICENSE for licensing terms. 3 4 package sampler 5 6 import ( 7 "math" 8 "time" 9 10 "github.com/MetalBlockchain/metalgo/utils/timer/mockable" 11 ) 12 13 var _ Uniform = (*uniformBest)(nil) 14 15 // Sampling is performed by using another implementation of the Uniform 16 // interface. 17 // 18 // Initialization attempts to find the best sampling algorithm given the dataset 19 // by performing a benchmark of the provided implementations. 20 type uniformBest struct { 21 Uniform 22 samplers []Uniform 23 maxSampleSize int 24 benchmarkIterations int 25 clock mockable.Clock 26 } 27 28 // NewBestUniform returns a new sampler 29 func NewBestUniform(expectedSampleSize int) Uniform { 30 return &uniformBest{ 31 samplers: []Uniform{ 32 &uniformReplacer{ 33 rng: globalRNG, 34 }, 35 &uniformResample{ 36 rng: globalRNG, 37 }, 38 }, 39 maxSampleSize: expectedSampleSize, 40 benchmarkIterations: 100, 41 } 42 } 43 44 func (s *uniformBest) Initialize(length uint64) { 45 s.Uniform = nil 46 bestDuration := time.Duration(math.MaxInt64) 47 48 sampleSize := s.maxSampleSize 49 if length < uint64(sampleSize) { 50 sampleSize = int(length) 51 } 52 53 samplerLoop: 54 for _, sampler := range s.samplers { 55 sampler.Initialize(length) 56 57 start := s.clock.Time() 58 for i := 0; i < s.benchmarkIterations; i++ { 59 if _, ok := sampler.Sample(sampleSize); !ok { 60 continue samplerLoop 61 } 62 } 63 end := s.clock.Time() 64 duration := end.Sub(start) 65 if duration < bestDuration { 66 bestDuration = duration 67 s.Uniform = sampler 68 } 69 } 70 71 s.Uniform.Reset() 72 }