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 }