mirror of
https://github.com/tendermint/tendermint.git
synced 2026-07-29 03:22:51 +00:00
e2e: use network size in load generator (#7019)
This commit is contained in:
@@ -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
@@ -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
@@ -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
|
||||
}()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user