Browse Source

e2e: use network size in load generator (#7019)

pull/7025/head
Sam Kleinman 3 years ago
committed by GitHub
parent
commit
c18470a5f1
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 40 additions and 31 deletions
  1. +2
    -2
      test/e2e/runner/evidence.go
  2. +16
    -21
      test/e2e/runner/load.go
  3. +22
    -8
      test/e2e/runner/main.go

+ 2
- 2
test/e2e/runner/evidence.go View File

@ -28,11 +28,11 @@ const lightClientEvidenceRatio = 4
// evidence and broadcasts it to a random node through the rpc endpoint `/broadcast_evidence`.
// Evidence is random and can be a mixture of LightClientAttackEvidence and
// DuplicateVoteEvidence.
func InjectEvidence(ctx context.Context, testnet *e2e.Testnet, amount int) error {
func InjectEvidence(ctx context.Context, r *rand.Rand, testnet *e2e.Testnet, amount int) error {
// select a random node
var targetNode *e2e.Node
for _, idx := range rand.Perm(len(testnet.Nodes)) {
for _, idx := range r.Perm(len(testnet.Nodes)) {
targetNode = testnet.Nodes[idx]
if targetNode.Mode == e2e.ModeSeed || targetNode.Mode == e2e.ModeLight {


+ 16
- 21
test/e2e/runner/load.go View File

@ -14,15 +14,15 @@ import (
// Load generates transactions against the network until the given context is
// canceled.
func Load(ctx context.Context, testnet *e2e.Testnet) error {
func Load(ctx context.Context, r *rand.Rand, testnet *e2e.Testnet) error {
// Since transactions are executed across all nodes in the network, we need
// to reduce transaction load for larger networks to avoid using too much
// CPU. This gives high-throughput small networks and low-throughput large ones.
// This also limits the number of TCP connections, since each worker has
// a connection to all nodes.
concurrency := len(testnet.Nodes) * 8
if concurrency > 64 {
concurrency = 64
concurrency := len(testnet.Nodes) * 2
if concurrency > 32 {
concurrency = 32
}
chTx := make(chan types.Tx)
@ -38,7 +38,7 @@ func Load(ctx context.Context, testnet *e2e.Testnet) error {
started := time.Now()
go loadGenerate(ctx, chTx, testnet.TxSize)
go loadGenerate(ctx, r, chTx, testnet.TxSize, len(testnet.Nodes))
for w := 0; w < concurrency; w++ {
go loadProcess(ctx, testnet, chTx, chSuccess)
@ -85,7 +85,7 @@ func Load(ctx context.Context, testnet *e2e.Testnet) error {
// generation is primarily the result of backpressure from the
// broadcast transaction, though there is still some timer-based
// limiting.
func loadGenerate(ctx context.Context, chTx chan<- types.Tx, size int64) {
func loadGenerate(ctx context.Context, r *rand.Rand, chTx chan<- types.Tx, txSize int64, networkSize int) {
timer := time.NewTimer(0)
defer timer.Stop()
defer close(chTx)
@ -101,8 +101,8 @@ func loadGenerate(ctx context.Context, chTx chan<- types.Tx, size int64) {
// This gives a reasonable load without putting too much data in the app.
id := rand.Int63() % 100 // nolint: gosec
bz := make([]byte, size)
_, err := rand.Read(bz) // nolint: gosec
bz := make([]byte, txSize)
_, err := r.Read(bz)
if err != nil {
panic(fmt.Sprintf("Failed to read random bytes: %v", err))
}
@ -114,30 +114,25 @@ func loadGenerate(ctx context.Context, chTx chan<- types.Tx, size int64) {
case chTx <- tx:
// sleep for a bit before sending the
// next transaction.
timer.Reset(loadGenerateWaitTime(size))
timer.Reset(loadGenerateWaitTime(r, networkSize))
}
}
}
func loadGenerateWaitTime(size int64) time.Duration {
func loadGenerateWaitTime(r *rand.Rand, size int) time.Duration {
const (
min = int64(10 * time.Millisecond)
max = int64(100 * time.Millisecond)
min = int64(250 * time.Millisecond)
max = int64(time.Second)
)
var (
baseJitter = rand.Int63n(max-min+1) + min // nolint: gosec
sizeFactor = size * int64(time.Millisecond)
sizeJitter = rand.Int63n(sizeFactor-min+1) + min // nolint: gosec
waitTime = time.Duration(baseJitter + sizeJitter)
baseJitter = r.Int63n(max-min+1) + min
sizeFactor = int64(size) * min
sizeJitter = r.Int63n(sizeFactor-min+1) + min
)
if size == 1 {
return waitTime / 2
}
return waitTime
return time.Duration(baseJitter + sizeJitter)
}
// loadProcess processes transactions


+ 22
- 8
test/e2e/runner/main.go View File

@ -3,6 +3,7 @@ package main
import (
"context"
"fmt"
"math/rand"
"os"
"strconv"
"time"
@ -13,9 +14,9 @@ import (
e2e "github.com/tendermint/tendermint/test/e2e/pkg"
)
var (
logger = log.MustNewDefaultLogger(log.LogFormatPlain, log.LogLevelInfo, false)
)
const randomSeed = 2308084734268
var logger = log.MustNewDefaultLogger(log.LogFormatPlain, log.LogLevelInfo, false)
func main() {
NewCLI().Run()
@ -67,6 +68,8 @@ func NewCLI() *CLI {
return err
}
r := rand.New(rand.NewSource(randomSeed)) // nolint: gosec
chLoadResult := make(chan error)
ctx, cancel := context.WithCancel(cmd.Context())
defer cancel()
@ -74,7 +77,7 @@ func NewCLI() *CLI {
lctx, loadCancel := context.WithCancel(ctx)
defer loadCancel()
go func() {
chLoadResult <- Load(lctx, cli.testnet)
chLoadResult <- Load(lctx, r, cli.testnet)
}()
startAt := time.Now()
if err = Start(ctx, cli.testnet); err != nil {
@ -95,7 +98,7 @@ func NewCLI() *CLI {
}
if cli.testnet.Evidence > 0 {
if err = InjectEvidence(ctx, cli.testnet, cli.testnet.Evidence); err != nil {
if err = InjectEvidence(ctx, r, cli.testnet, cli.testnet.Evidence); err != nil {
return err
}
if err = Wait(ctx, cli.testnet, 5); err != nil { // ensure chain progress
@ -212,7 +215,11 @@ func NewCLI() *CLI {
Use: "load",
Short: "Generates transaction load until the command is canceled",
RunE: func(cmd *cobra.Command, args []string) (err error) {
return Load(context.Background(), cli.testnet)
return Load(
cmd.Context(),
rand.New(rand.NewSource(randomSeed)), // nolint: gosec
cli.testnet,
)
},
})
@ -230,7 +237,12 @@ func NewCLI() *CLI {
}
}
return InjectEvidence(cmd.Context(), cli.testnet, amount)
return InjectEvidence(
cmd.Context(),
rand.New(rand.NewSource(randomSeed)), // nolint: gosec
cli.testnet,
amount,
)
},
})
@ -302,10 +314,12 @@ Does not run any perbutations.
ctx, cancel := context.WithCancel(cmd.Context())
defer cancel()
r := rand.New(rand.NewSource(randomSeed)) // nolint: gosec
lctx, loadCancel := context.WithCancel(ctx)
defer loadCancel()
go func() {
err := Load(lctx, cli.testnet)
err := Load(lctx, r, cli.testnet)
chLoadResult <- err
}()


Loading…
Cancel
Save