Skip to content

Commit

Permalink
Make simulation use a transition matrix for block size
Browse files Browse the repository at this point in the history
This enables simulating periods of high load, and periods of low to no load.
(low load because future ops will still terminate in that time frame)
  • Loading branch information
ValarDragon committed Oct 29, 2018
1 parent 855e0ac commit e4b5e2c
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 18 deletions.
1 change: 1 addition & 0 deletions PENDING.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ IMPROVEMENTS

* SDK
- #2573 [x/distribution] add accum invariance
- \#1924 [simulation] Use a transition matrix for block size

* Tendermint

Expand Down
2 changes: 1 addition & 1 deletion client/lcd/certificates.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ func generateSelfSignedCert(host string) (certBytes []byte, priv *ecdsa.PrivateK
KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign,
ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
BasicConstraintsValid: true,
IsCA: true,
IsCA: true,
}
hosts := strings.Split(host, ",")
for _, h := range hosts {
Expand Down
6 changes: 6 additions & 0 deletions x/mock/simulation/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,10 @@ var (
{10, 50, 5},
{0, 10, 1000},
})
// 3 states: rand in range [0, 4*provided blocksize], rand in range [0, 2 * provided blocksize], 0
blockSizeTransitionMatrix, _ = CreateTransitionMatrix([][]int{
{85, 5, 0},
{15, 92, 1},
{0, 3, 99},
})
)
41 changes: 24 additions & 17 deletions x/mock/simulation/random_simulate_blocks.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ func SimulateFromSeed(tb testing.TB, app *baseapp.BaseApp,
blockLogBuilders = make([]*strings.Builder, numBlocks)
}
displayLogs := logPrinter(testingMode, blockLogBuilders)
blockSimulator := createBlockSimulator(testingMode, tb, t, event, invariants, ops, operationQueue, timeOperationQueue, numBlocks, displayLogs)
blockSimulator := createBlockSimulator(testingMode, tb, t, event, invariants, ops, operationQueue, timeOperationQueue, numBlocks, blockSize, displayLogs)
if !testingMode {
b.ResetTimer()
} else {
Expand Down Expand Up @@ -142,7 +142,6 @@ func SimulateFromSeed(tb testing.TB, app *baseapp.BaseApp,
}

ctx := app.NewContext(false, header)
thisBlockSize := getBlockSize(r, blockSize)

// Run queued operations. Ignores blocksize if blocksize is too small
logWriter("Queued operations")
Expand All @@ -153,9 +152,8 @@ func SimulateFromSeed(tb testing.TB, app *baseapp.BaseApp,
assertAllInvariants(t, app, header, invariants, "QueuedOperations", displayLogs)
}

thisBlockSize = thisBlockSize - numQueuedOpsRan - numQueuedTimeOpsRan
logWriter("Standard operations")
operations := blockSimulator(thisBlockSize, r, app, ctx, accs, header, logWriter)
operations := blockSimulator(r, app, ctx, accs, header, logWriter)
opCount += operations + numQueuedOpsRan + numQueuedTimeOpsRan
if testingMode {
// Make sure invariants hold at end of block
Expand Down Expand Up @@ -200,9 +198,14 @@ func SimulateFromSeed(tb testing.TB, app *baseapp.BaseApp,

// Returns a function to simulate blocks. Written like this to avoid constant parameters being passed everytime, to minimize
// memory overhead
func createBlockSimulator(testingMode bool, tb testing.TB, t *testing.T, event func(string), invariants []Invariant, ops []WeightedOperation, operationQueue map[int][]Operation, timeOperationQueue []FutureOperation, totalNumBlocks int, displayLogs func()) func(
blocksize int, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accounts []Account, header abci.Header, logWriter func(string)) (opCount int) {
totalOpWeight := 0
func createBlockSimulator(testingMode bool, tb testing.TB, t *testing.T, event func(string), invariants []Invariant, ops []WeightedOperation, operationQueue map[int][]Operation, timeOperationQueue []FutureOperation, totalNumBlocks int, avgBlockSize int, displayLogs func()) func(
r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context, accounts []Account, header abci.Header, logWriter func(string)) (opCount int) {
var (
lastBlocksizeState = 0 // state for [4 * uniform distribution]
totalOpWeight = 0
blocksize int
)

for i := 0; i < len(ops); i++ {
totalOpWeight += ops[i].Weight
}
Expand All @@ -217,8 +220,10 @@ func createBlockSimulator(testingMode bool, tb testing.TB, t *testing.T, event f
// shouldn't happen
return ops[0].Op
}
return func(blocksize int, r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context,

return func(r *rand.Rand, app *baseapp.BaseApp, ctx sdk.Context,
accounts []Account, header abci.Header, logWriter func(string)) (opCount int) {
lastBlocksizeState, blocksize = getBlockSize(r, lastBlocksizeState, avgBlockSize)
for j := 0; j < blocksize; j++ {
logUpdate, futureOps, err := selectOp(r)(r, app, ctx, accounts, event)
if err != nil {
Expand Down Expand Up @@ -253,16 +258,18 @@ func getTestingMode(tb testing.TB) (testingMode bool, t *testing.T, b *testing.B
return
}

func getBlockSize(r *rand.Rand, blockSize int) int {
load := r.Float64()
switch {
case load < 0.33:
return 0
case load < 0.66:
return r.Intn(blockSize * 2)
default:
return r.Intn(blockSize * 4)
func getBlockSize(r *rand.Rand, lastBlockSizeState, avgBlockSize int) (state, blocksize int) {
// TODO: Make blockSizeTransitionMatrix non-global
// TODO: Make default blocksize transitition matrix actually make the average blocksize equal to avgBlockSize
state = blockSizeTransitionMatrix.NextState(r, lastBlockSizeState)
if state == 0 {
blocksize = r.Intn(avgBlockSize * 4)
} else if state == 1 {
blocksize = r.Intn(avgBlockSize * 2)
} else {
blocksize = 0
}
return
}

// adds all future operations into the operation queue.
Expand Down

0 comments on commit e4b5e2c

Please sign in to comment.