github.com/cockroachdb/pebble@v1.1.1-0.20240513155919-3622ade60459/metamorphic/config.go (about)

     1  // Copyright 2019 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 metamorphic
     6  
     7  import "github.com/cockroachdb/pebble/internal/randvar"
     8  
     9  type opType int
    10  
    11  const (
    12  	batchAbort opType = iota
    13  	batchCommit
    14  	dbCheckpoint
    15  	dbClose
    16  	dbCompact
    17  	dbFlush
    18  	dbRatchetFormatMajorVersion
    19  	dbRestart
    20  	iterClose
    21  	iterFirst
    22  	iterLast
    23  	iterNext
    24  	iterNextWithLimit
    25  	iterNextPrefix
    26  	iterCanSingleDelete
    27  	iterPrev
    28  	iterPrevWithLimit
    29  	iterSeekGE
    30  	iterSeekGEWithLimit
    31  	iterSeekLT
    32  	iterSeekLTWithLimit
    33  	iterSeekPrefixGE
    34  	iterSetBounds
    35  	iterSetOptions
    36  	newBatch
    37  	newIndexedBatch
    38  	newIter
    39  	newIterUsingClone
    40  	newSnapshot
    41  	readerGet
    42  	snapshotClose
    43  	writerApply
    44  	writerDelete
    45  	writerDeleteRange
    46  	writerIngest
    47  	writerMerge
    48  	writerRangeKeyDelete
    49  	writerRangeKeySet
    50  	writerRangeKeyUnset
    51  	writerSet
    52  	writerSingleDelete
    53  )
    54  
    55  type config struct {
    56  	// Weights for the operation mix to generate. ops[i] corresponds to the
    57  	// weight for opType(i).
    58  	ops []int
    59  
    60  	// newPrefix configures the probability that when generating a new user key,
    61  	// the generated key uses a new key prefix rather than an existing prefix
    62  	// with a suffix.
    63  	newPrefix float64
    64  	// writeSuffixDist defines the distribution of key suffixes during writing.
    65  	// It's a dynamic randvar to roughly emulate workloads with MVCC timestamps,
    66  	// skewing towards most recent timestamps.
    67  	writeSuffixDist randvar.Dynamic
    68  
    69  	// TODO(peter): unimplemented
    70  	// keyDist        randvar.Dynamic
    71  	// keySizeDist    randvar.Static
    72  	// valueSizeDist  randvar.Static
    73  	// updateFrac     float64
    74  	// lowerBoundFrac float64
    75  	// upperBoundFrac float64
    76  }
    77  
    78  func (c config) withNewPrefixProbability(p float64) config {
    79  	c.newPrefix = p
    80  	return c
    81  }
    82  
    83  func (c config) withOpWeight(op opType, weight int) config {
    84  	c.ops[op] = weight
    85  	return c
    86  }
    87  
    88  var presetConfigs = []config{
    89  	defaultConfig(),
    90  	// Generate a configuration that helps exercise code paths dependent on many
    91  	// versions of keys with the same prefixes. The default configuration does
    92  	// not tend to generate many versions of the same key. Additionally, its
    93  	// relatively high weight for deletion write operations makes it less likely
    94  	// that we'll accumulate enough versions to exercise some code paths (eg,
    95  	// see #2921 which requires >16 SETs for versions of the same prefix to
    96  	// reside in a single block to exercise the code path).
    97  	//
    98  	// To encourage generation of many versions of the same keys, generate a new
    99  	// prefix only 4% of the time when generating a new key. The remaining 96%
   100  	// of new key generations will use an existing prefix. To keep the size of
   101  	// the database growing, we also reduce the probability of delete write
   102  	// operations significantly.
   103  	defaultConfig().
   104  		withNewPrefixProbability(0.04).
   105  		withOpWeight(writerDeleteRange, 1).
   106  		withOpWeight(writerDelete, 5).
   107  		withOpWeight(writerSingleDelete, 5).
   108  		withOpWeight(writerMerge, 0),
   109  }
   110  
   111  func defaultConfig() config {
   112  	return config{
   113  		// dbClose is not in this list since it is deterministically generated once, at the end of the test.
   114  		ops: []int{
   115  			batchAbort:                  5,
   116  			batchCommit:                 5,
   117  			dbCheckpoint:                1,
   118  			dbCompact:                   1,
   119  			dbFlush:                     2,
   120  			dbRatchetFormatMajorVersion: 1,
   121  			dbRestart:                   2,
   122  			iterClose:                   5,
   123  			iterFirst:                   100,
   124  			iterLast:                    100,
   125  			iterNext:                    100,
   126  			iterNextWithLimit:           20,
   127  			iterNextPrefix:              20,
   128  			iterCanSingleDelete:         20,
   129  			iterPrev:                    100,
   130  			iterPrevWithLimit:           20,
   131  			iterSeekGE:                  100,
   132  			iterSeekGEWithLimit:         20,
   133  			iterSeekLT:                  100,
   134  			iterSeekLTWithLimit:         20,
   135  			iterSeekPrefixGE:            100,
   136  			iterSetBounds:               100,
   137  			iterSetOptions:              10,
   138  			newBatch:                    5,
   139  			newIndexedBatch:             5,
   140  			newIter:                     10,
   141  			newIterUsingClone:           5,
   142  			newSnapshot:                 10,
   143  			readerGet:                   100,
   144  			snapshotClose:               10,
   145  			writerApply:                 10,
   146  			writerDelete:                100,
   147  			writerDeleteRange:           50,
   148  			writerIngest:                100,
   149  			writerMerge:                 100,
   150  			writerRangeKeySet:           10,
   151  			writerRangeKeyUnset:         10,
   152  			writerRangeKeyDelete:        5,
   153  			writerSet:                   100,
   154  			writerSingleDelete:          50,
   155  		},
   156  		// Use a new prefix 75% of the time (and 25% of the time use an existing
   157  		// prefix with an alternative suffix).
   158  		newPrefix: 0.75,
   159  		// Use a skewed distribution of suffixes to mimic MVCC timestamps. The
   160  		// range will be widened whenever a suffix is found to already be in use
   161  		// for a particular prefix.
   162  		writeSuffixDist: mustDynamic(randvar.NewSkewedLatest(0, 1, 0.99)),
   163  	}
   164  }
   165  
   166  func mustDynamic(dyn randvar.Dynamic, err error) randvar.Dynamic {
   167  	if err != nil {
   168  		panic(err)
   169  	}
   170  	return dyn
   171  }