Skip to content

Commit

Permalink
a
Browse files Browse the repository at this point in the history
  • Loading branch information
wenyihu6 committed Aug 1, 2023
1 parent 131f8d6 commit 389fd14
Show file tree
Hide file tree
Showing 20 changed files with 720 additions and 106 deletions.
30 changes: 30 additions & 0 deletions pkg/kv/kvserver/asim/gen/generator.go
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,36 @@ const (
WeightedRandom
)

func (p PlacementType) String() string {
switch p {
case Uniform:
return "uniform"
case Skewed:
return "skewed"
case Random:
return "random"
case WeightedRandom:
return "weighted_rand"
default:
panic("unknown placement type")
}
}

func (p PlacementType) GetGeneratorType(s string) PlacementType {
switch s {
case "uniform":
return Uniform
case "skewed":
return Skewed
case "random":
return Random
case "weighted_rand":
return WeightedRandom
default:
panic(fmt.Sprintf("unknown placement type %s", s))
}
}

// BaseRanges provide fundamental range functionality and are embedded in
// specialized range structs. These structs implement the RangeGen interface
// which is then utilized to generate allocator simulation. Key structs that
Expand Down
4 changes: 3 additions & 1 deletion pkg/kv/kvserver/asim/state/config_loader.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ import (
"github.com/cockroachdb/cockroach/pkg/roachpb"
)

var ClusterOptions = [...]string{"single_region", "single_region_multi_store", "multi_region", "complex"}
var SingleRegionClusterOptions = [...]string{"single_region", "single_region_multi_store"}
var MultiRegionClusterOptions = [...]string{"multi_region", "complex"}
var AllClusterOptions = [...]string{"single_region", "single_region_multi_store", "multi_region", "complex"}

// TODO(kvoli): Add a loader/translator for the existing
// []*roachpb.StoreDescriptor configurations in kvserver/*_test.go and
Expand Down
2 changes: 1 addition & 1 deletion pkg/kv/kvserver/asim/state/new_state.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ func newWeighted(weightedStores []float64) weighted {
cumulativeWeights[i] = prefixSumWeight
}
if cumulativeWeights[len(weightedStores)-1] != float64(1) {
panic(fmt.Sprintf("total cumulative weights for all stores should sum up to one but got %.2f\n",
panic(fmt.Sprintf("total cumulative weights for all stores should sum up to 1 but got %.2f\n",
cumulativeWeights[len(weightedStores)-1]))
}
return weighted{cumulativeWeights: cumulativeWeights}
Expand Down
2 changes: 1 addition & 1 deletion pkg/kv/kvserver/asim/tests/datadriven_simulation_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ import (
// ....└── [11 12 13 14 15]
func TestDataDriven(t *testing.T) {
ctx := context.Background()
dir := datapathutils.TestDataPath(t, ".")
dir := datapathutils.TestDataPath(t, "non_rand")
datadriven.Walk(t, dir, func(t *testing.T, path string) {
if strings.Contains(path, "example_fulldisk") {
skip.WithIssue(t, 105904, "asim is non-deterministic")
Expand Down
59 changes: 51 additions & 8 deletions pkg/kv/kvserver/asim/tests/default_settings.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@
package tests

import (
"fmt"
"text/tabwriter"
"time"

"github.com/cockroachdb/cockroach/pkg/kv/kvserver/asim/config"
"github.com/cockroachdb/cockroach/pkg/kv/kvserver/asim/event"
"github.com/cockroachdb/cockroach/pkg/kv/kvserver/asim/gen"
Expand All @@ -19,6 +23,12 @@ import (
// This file defines the default parameters for allocator simulator testing,
// including configurations for the cluster, ranges, load, static settings,
// static events, assertions, and plot settings.
const (
defaultNumIterations = 3
defaultSeed = int64(42)
defaultDuration = 10 * time.Minute
defaultVerbosity = false
)

const (
defaultNodes = 3
Expand Down Expand Up @@ -64,7 +74,7 @@ func defaultLoadGen() gen.BasicLoad {
const (
defaultRanges = 1
defaultPlacementType = gen.Uniform
defaultReplicationFactor = 1
defaultReplicationFactor = 3
defaultBytes = 0
)

Expand Down Expand Up @@ -110,22 +120,55 @@ func defaultPlotSettings() plotSettings {
}

type rangeGenSettings struct {
rangeKeyGenType generatorType
keySpaceGenType generatorType
weightedRand []float64
placementType gen.PlacementType
replicationFactor int
rangeGenType generatorType
keySpaceGenType generatorType
weightedRand []float64
}

func (t rangeGenSettings) printRangeGenSettings(w *tabwriter.Writer) {
if _, err := fmt.Fprintf(w,
"range_gen_settings ->\tplacementType=%v\treplicationFactor=%v\trangeGenType=%v\tkeySpaceGenType=%v\tweightedRand=%v\n",
t.placementType, t.replicationFactor, t.rangeGenType, t.keySpaceGenType, t.weightedRand); err != nil {
panic(err)
}
}

const (
defaultRangeKeyGenType = uniformGenerator
defaultRangeGenType = uniformGenerator
defaultKeySpaceGenType = uniformGenerator
)

var defaultWeightedRand []float64

func defaultRangeGenSettings() rangeGenSettings {
return rangeGenSettings{
rangeKeyGenType: defaultRangeKeyGenType,
keySpaceGenType: defaultKeySpaceGenType,
weightedRand: defaultWeightedRand,
placementType: defaultPlacementType,
replicationFactor: defaultReplicationFactor,
rangeGenType: defaultRangeGenType,
keySpaceGenType: defaultKeySpaceGenType,
weightedRand: defaultWeightedRand,
}
}

type clusterGenSettings struct {
clusterGenType clusterConfigType
}

func (c clusterGenSettings) printClusterGenSettings(w *tabwriter.Writer) {
if _, err := fmt.Fprintf(w,
"cluster_gen_settings ->\tclusterGenType=%v\t\n", c.clusterGenType); err != nil {
panic(err)
}
}

const (
defaultClusterGenType = multiRegion
)

func defaultClusterGenSettings() clusterGenSettings {
return clusterGenSettings{
clusterGenType: defaultClusterGenType,
}
}
12 changes: 10 additions & 2 deletions pkg/kv/kvserver/asim/tests/helpers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,25 @@ import (
"testing"
"time"

"github.com/cockroachdb/cockroach/pkg/kv/kvserver/asim/gen"
"github.com/cockroachdb/datadriven"
"github.com/stretchr/testify/require"
)

// TODO(kvoli): Upstream the scan implementations for the float64 and
// time.Duration types to the datadriven testing repository.
func scanArg(t *testing.T, d *datadriven.TestData, key string, dest interface{}) {
var tmp string
switch dest := dest.(type) {
case *string, *int, *int64, *uint64, *bool, *time.Duration, *float64, *[]int, *[]float64:
d.ScanArgs(t, key, dest)
case *gen.PlacementType:
d.ScanArgs(t, key, &tmp)
*dest = dest.GetGeneratorType(tmp)
case *generatorType:
d.ScanArgs(t, key, &tmp)
*dest = dest.getGeneratorType(tmp)
case *clusterConfigType:
d.ScanArgs(t, key, &tmp)
*dest = dest.getClusterConfigType(tmp)
default:
require.Fail(t, "unsupported type %T", dest)
}
Expand Down
103 changes: 87 additions & 16 deletions pkg/kv/kvserver/asim/tests/rand_framework.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,13 @@
package tests

import (
"bytes"
"context"
"fmt"
"math"
"math/rand"
"strings"
"testing"
"text/tabwriter"
"time"

"github.com/cockroachdb/cockroach/pkg/kv/kvserver/asim"
Expand All @@ -34,17 +35,52 @@ type testRandOptions struct {
staticEvents bool
}

func (t testRandOptions) printRandOptions(w *tabwriter.Writer) {
if _, err := fmt.Fprintf(w,
"rand_options\tcluster=%t\tranges=%t\tload=%t\tstaticSettings=%t\tstaticEvents=%t\n", t.cluster, t.ranges, t.load, t.staticSettings, t.staticEvents); err != nil {
panic(err)
}
}

type testSettings struct {
numIterations int
duration time.Duration
verbose bool
randSource *rand.Rand
assertions []SimulationAssertion
randOptions testRandOptions
clusterGen clusterGenSettings
rangeGen rangeGenSettings
}

func (t testSettings) printTestSettings(w *tabwriter.Writer) {
if _, err := fmt.Fprintf(w,
"settings\tnum_iterations=%v\tduration=%s\n", t.numIterations, t.duration.Round(time.Second)); err != nil {
panic(err)
}

t.randOptions.printRandOptions(w)
if t.randOptions.cluster {
_, _ = fmt.Fprint(w, "rand_cluster=true\t")
t.clusterGen.printClusterGenSettings(w)
} else {
_, _ = fmt.Fprintln(w, "rand_cluster=false")
}

if t.randOptions.ranges {
_, _ = fmt.Fprint(w, "rand_ranges=true\t")
t.rangeGen.printRangeGenSettings(w)
} else {
_, _ = fmt.Fprintln(w, "rand_cluster=false")
}

_, _ = fmt.Fprintf(w, "rand_load=%t\n", t.randOptions.load)
_, _ = fmt.Fprintf(w, "rand_events=%t\n", t.randOptions.staticEvents)
_, _ = fmt.Fprintf(w, "rand_settings=%t\n", t.randOptions.staticSettings)
}

type randTestingFramework struct {
recordBuf *strings.Builder
s testSettings
rangeGenerator generator
keySpaceGenerator generator
Expand All @@ -56,9 +92,12 @@ func newRandTestingFramework(settings testSettings) randTestingFramework {
"Max number of ranges specified (%d) is greater than number of keys in key space (%d) ",
defaultMaxRange, defaultMinKeySpace))
}
rangeGenerator := newGenerator(settings.randSource, defaultMinRange, defaultMaxRange, settings.rangeGen.rangeKeyGenType)
rangeGenerator := newGenerator(settings.randSource, defaultMinRange, defaultMaxRange, settings.rangeGen.rangeGenType)
keySpaceGenerator := newGenerator(settings.randSource, defaultMinKeySpace, defaultMaxKeySpace, settings.rangeGen.keySpaceGenType)
var buf strings.Builder

return randTestingFramework{
recordBuf: &buf,
s: settings,
rangeGenerator: rangeGenerator,
keySpaceGenerator: keySpaceGenerator,
Expand Down Expand Up @@ -114,27 +153,36 @@ func (f randTestingFramework) runRandTest() (asim.History, bool, string) {
return history, failed, reason
}

func (f randTestingFramework) runRandTestRepeated(t *testing.T) {
func (f randTestingFramework) runRandTestRepeated() {
numIterations := f.s.numIterations
runs := make([]asim.History, numIterations)
failureExists := false
var buf strings.Builder
for i := 0; i < numIterations; i++ {
if i == 0 {
_, _ = fmt.Fprintln(f.recordBuf, "----------------------------------")
}
_, _ = fmt.Fprintf(f.recordBuf, "sample%d: start running\n", i+1)
history, failed, reason := f.runRandTest()
runs[i] = history
if failed {
failureExists = true
fmt.Fprintf(&buf, "failed assertion sample %d\n%s", i+1, reason)
_, _ = fmt.Fprintf(f.recordBuf, "sample%d: failed assertion\n%s", i+1, reason)
} else {
_, _ = fmt.Fprintf(f.recordBuf, "sample%d: pass\n", i+1)
}
_, _ = fmt.Fprintln(f.recordBuf, "----------------------------------")
}

if f.s.verbose {
plotAllHistory(runs, &buf)
plotAllHistory(runs, f.recordBuf)
}
}

if failureExists {
t.Fatal(buf.String())
}
func (f randTestingFramework) printResults() string {
var buf bytes.Buffer
w := tabwriter.NewWriter(&buf, 4, 0, 2, ' ', 0)
f.s.printTestSettings(w)
_, _ = fmt.Fprintf(w, "%s", f.recordBuf.String())
_ = w.Flush()
return buf.String()
}

// loadClusterInfo creates a LoadedCluster from a matching ClusterInfo based on
Expand All @@ -156,7 +204,7 @@ func plotAllHistory(runs []asim.History, buf *strings.Builder) {
history := runs[i]
ts := metrics.MakeTS(history.Recorded)
statTS := ts[stat]
buf.WriteString("\n")
buf.WriteString(fmt.Sprintf("sample%d\n", i+1))
buf.WriteString(asciigraph.PlotMany(
statTS,
asciigraph.Caption(stat),
Expand Down Expand Up @@ -203,28 +251,51 @@ func convertInt64ToInt(num int64) int {
}

func (f randTestingFramework) randomBasicRangesGen() gen.RangeGen {
if len(f.s.rangeGen.weightedRand) == 0 {
switch placementType := f.s.rangeGen.placementType; placementType {
case gen.Uniform, gen.Skewed:
if len(f.s.rangeGen.weightedRand) != 0 {
panic("set placement_type to weighted_rand to use weightedRand")
}
return gen.BasicRanges{
BaseRanges: gen.BaseRanges{
Ranges: convertInt64ToInt(f.rangeGenerator.key()),
KeySpace: convertInt64ToInt(f.keySpaceGenerator.key()),
ReplicationFactor: f.s.rangeGen.replicationFactor,
Bytes: defaultBytes,
},
PlacementType: placementType,
}
case gen.Random:
if len(f.s.rangeGen.weightedRand) != 0 {
panic("set placement_type to weighted_rand to use weightedRand")
}
return RandomizedBasicRanges{
BaseRanges: gen.BaseRanges{
Ranges: convertInt64ToInt(f.rangeGenerator.key()),
KeySpace: convertInt64ToInt(f.keySpaceGenerator.key()),
ReplicationFactor: defaultReplicationFactor,
ReplicationFactor: f.s.rangeGen.replicationFactor,
Bytes: defaultBytes,
},
placementType: gen.Random,
randSource: f.s.randSource,
}
} else {

case gen.WeightedRandom:
if len(f.s.rangeGen.weightedRand) == 0 {
panic("set weightedRand array for stores properly to use the weighted_rand placementType")
}
return WeightedRandomizedBasicRanges{
BaseRanges: gen.BaseRanges{
Ranges: convertInt64ToInt(f.rangeGenerator.key()),
KeySpace: convertInt64ToInt(f.keySpaceGenerator.key()),
ReplicationFactor: defaultReplicationFactor,
ReplicationFactor: f.s.rangeGen.replicationFactor,
Bytes: defaultBytes,
},
placementType: gen.WeightedRandom,
randSource: f.s.randSource,
weightedRand: f.s.rangeGen.weightedRand,
}
default:
panic("unknown ranges placementType")
}
}
Loading

0 comments on commit 389fd14

Please sign in to comment.