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  }