ceremonyclient/pebble/metamorphic/config.go

190 lines
5.4 KiB
Go
Raw Normal View History

2024-01-03 07:31:42 +00:00
// Copyright 2019 The LevelDB-Go and Pebble Authors. All rights reserved. Use
// of this source code is governed by a BSD-style license that can be found in
// the LICENSE file.
package metamorphic
import "github.com/cockroachdb/pebble/internal/randvar"
type opType int
const (
batchAbort opType = iota
batchCommit
dbCheckpoint
dbClose
dbCompact
dbFlush
dbRatchetFormatMajorVersion
dbRestart
iterClose
iterFirst
iterLast
iterNext
iterNextWithLimit
iterNextPrefix
iterCanSingleDelete
iterPrev
iterPrevWithLimit
iterSeekGE
iterSeekGEWithLimit
iterSeekLT
iterSeekLTWithLimit
iterSeekPrefixGE
iterSetBounds
iterSetOptions
newBatch
newIndexedBatch
newIter
newIterUsingClone
newSnapshot
readerGet
replicate
snapshotClose
writerApply
writerDelete
writerDeleteRange
writerIngest
writerMerge
writerRangeKeyDelete
writerRangeKeySet
writerRangeKeyUnset
writerSet
writerSingleDelete
)
type config struct {
// Weights for the operation mix to generate. ops[i] corresponds to the
// weight for opType(i).
ops []int
// newPrefix configures the probability that when generating a new user key,
// the generated key uses a new key prefix rather than an existing prefix
// with a suffix.
newPrefix float64
// writeSuffixDist defines the distribution of key suffixes during writing.
// It's a dynamic randvar to roughly emulate workloads with MVCC timestamps,
// skewing towards most recent timestamps.
writeSuffixDist randvar.Dynamic
// numInstances defines the number of pebble instances created for this
// metamorphic test run.
numInstances int
// TODO(peter): unimplemented
// keyDist randvar.Dynamic
// keySizeDist randvar.Static
// valueSizeDist randvar.Static
// updateFrac float64
// lowerBoundFrac float64
// upperBoundFrac float64
}
func (c config) withNewPrefixProbability(p float64) config {
c.newPrefix = p
return c
}
func (c config) withOpWeight(op opType, weight int) config {
c.ops[op] = weight
return c
}
var presetConfigs = []config{
defaultConfig(),
// Generate a configuration that helps exercise code paths dependent on many
// versions of keys with the same prefixes. The default configuration does
// not tend to generate many versions of the same key. Additionally, its
// relatively high weight for deletion write operations makes it less likely
// that we'll accumulate enough versions to exercise some code paths (eg,
// see #2921 which requires >16 SETs for versions of the same prefix to
// reside in a single block to exercise the code path).
//
// To encourage generation of many versions of the same keys, generate a new
// prefix only 4% of the time when generating a new key. The remaining 96%
// of new key generations will use an existing prefix. To keep the size of
// the database growing, we also reduce the probability of delete write
// operations significantly.
defaultConfig().
withNewPrefixProbability(0.04).
withOpWeight(writerDeleteRange, 1).
withOpWeight(writerDelete, 5).
withOpWeight(writerSingleDelete, 5).
withOpWeight(writerMerge, 0),
}
var multiInstancePresetConfig = multiInstanceConfig()
func defaultConfig() config {
return config{
// dbClose is not in this list since it is deterministically generated once, at the end of the test.
ops: []int{
batchAbort: 5,
batchCommit: 5,
dbCheckpoint: 1,
dbCompact: 1,
dbFlush: 2,
dbRatchetFormatMajorVersion: 1,
dbRestart: 2,
iterClose: 5,
iterFirst: 100,
iterLast: 100,
iterNext: 100,
iterNextWithLimit: 20,
iterNextPrefix: 20,
iterCanSingleDelete: 20,
iterPrev: 100,
iterPrevWithLimit: 20,
iterSeekGE: 100,
iterSeekGEWithLimit: 20,
iterSeekLT: 100,
iterSeekLTWithLimit: 20,
iterSeekPrefixGE: 100,
iterSetBounds: 100,
iterSetOptions: 10,
newBatch: 5,
newIndexedBatch: 5,
newIter: 10,
newIterUsingClone: 5,
newSnapshot: 10,
readerGet: 100,
replicate: 0,
snapshotClose: 10,
writerApply: 10,
writerDelete: 100,
writerDeleteRange: 50,
writerIngest: 100,
writerMerge: 100,
writerRangeKeySet: 10,
writerRangeKeyUnset: 10,
writerRangeKeyDelete: 5,
writerSet: 100,
writerSingleDelete: 50,
},
// Use a new prefix 75% of the time (and 25% of the time use an existing
// prefix with an alternative suffix).
newPrefix: 0.75,
// Use a skewed distribution of suffixes to mimic MVCC timestamps. The
// range will be widened whenever a suffix is found to already be in use
// for a particular prefix.
writeSuffixDist: mustDynamic(randvar.NewSkewedLatest(0, 1, 0.99)),
}
}
func multiInstanceConfig() config {
cfg := defaultConfig()
cfg.ops[replicate] = 5
// Single deletes and merges are disabled in multi-instance mode, as
// replicateOp doesn't support them.
cfg.ops[writerSingleDelete] = 0
cfg.ops[writerMerge] = 0
return cfg
}
func mustDynamic(dyn randvar.Dynamic, err error) randvar.Dynamic {
if err != nil {
panic(err)
}
return dyn
}