Skip to content

Commit

Permalink
test: add the loadtime tool (Backport #9342) (#9358)
Browse files Browse the repository at this point in the history
* test: add the loadtime tool (#9342)

This pull request adds the loadtime tool. This tool leverages the tm-load-test framework. Using the framework means that the only real logic that needs to be written is the logic for Tx generation. The framework does the rest.

The tool writes a set of metadata into the transaction, including the current transaction rate, number of connections, specified size of the transaction, and the current time.

* lint
  • Loading branch information
williambanfield authored Sep 2, 2022
1 parent 29c5a06 commit f573d3d
Show file tree
Hide file tree
Showing 11 changed files with 680 additions and 14 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ terraform.tfstate
terraform.tfstate.backup
terraform.tfstate.d
profile\.out
test/app/grpc_client
test/loadtime/build
test/e2e/build
test/e2e/networks/*/
test/logs
Expand Down
20 changes: 10 additions & 10 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,6 @@ require (
github.com/btcsuite/btcd v0.22.1
github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce
github.com/cenkalti/backoff v2.2.1+incompatible // indirect
github.com/facebookgo/ensure v0.0.0-20160127193407-b4ab57deab51 // indirect
github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 // indirect
github.com/facebookgo/subset v0.0.0-20150612182917-8dac2c3c4870 // indirect
github.com/fortytw2/leaktest v1.3.0
github.com/go-kit/kit v0.12.0
github.com/go-kit/log v0.2.1
Expand All @@ -28,9 +25,9 @@ require (
github.com/ory/dockertest v3.3.5+incompatible
github.com/pkg/errors v0.9.1
github.com/prometheus/client_golang v1.12.2
github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475
github.com/rs/cors v1.8.2
github.com/sasha-s/go-deadlock v0.2.1-0.20190427202633-1595213edefa
github.com/sasha-s/go-deadlock v0.3.1
github.com/snikch/goodman v0.0.0-20171125024755-10e37e294daa
github.com/spf13/cobra v1.5.0
github.com/spf13/viper v1.12.0
Expand All @@ -50,6 +47,11 @@ require (
github.com/vektra/mockery/v2 v2.14.0
)

require (
github.com/informalsystems/tm-load-test v1.0.0
google.golang.org/protobuf v1.28.0
)

require (
4d63.com/gochecknoglobals v0.1.0 // indirect
github.com/Antonboom/errname v0.1.7 // indirect
Expand Down Expand Up @@ -109,7 +111,7 @@ require (
github.com/gofrs/flock v0.8.1 // indirect
github.com/gofrs/uuid v4.2.0+incompatible // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/snappy v0.0.1 // indirect
github.com/golang/snappy v0.0.3 // indirect
github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2 // indirect
github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a // indirect
github.com/golangci/go-misc v0.0.0-20220329215616-d24fe342adfe // indirect
Expand All @@ -127,7 +129,6 @@ require (
github.com/gostaticanalysis/forcetypeassert v0.1.0 // indirect
github.com/gostaticanalysis/nilerr v0.1.1 // indirect
github.com/gostaticanalysis/testutil v0.4.0 // indirect
github.com/gotestyourself/gotestyourself v2.2.0+incompatible // indirect
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 // indirect
github.com/gtank/ristretto255 v0.1.2 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
Expand Down Expand Up @@ -162,7 +163,7 @@ require (
github.com/mbilski/exhaustivestruct v1.2.0 // indirect
github.com/mgechev/dots v0.0.0-20210922191527-e955255bf517 // indirect
github.com/mgechev/revive v1.2.1 // indirect
github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643 // indirect
github.com/mimoo/StrobeGo v0.0.0-20210601165009-122bf33a46e0 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/moby/buildkit v0.10.3 // indirect
Expand Down Expand Up @@ -196,6 +197,7 @@ require (
github.com/ryancurrah/gomodguard v1.2.4 // indirect
github.com/ryanrolds/sqlclosecheck v0.3.0 // indirect
github.com/sanposhiho/wastedassign/v2 v2.0.6 // indirect
github.com/satori/go.uuid v1.2.0 // indirect
github.com/securego/gosec/v2 v2.12.0 // indirect
github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c // indirect
github.com/sirupsen/logrus v1.9.0 // indirect
Expand Down Expand Up @@ -234,11 +236,9 @@ require (
golang.org/x/text v0.3.7 // indirect
golang.org/x/tools v0.1.12 // indirect
google.golang.org/genproto v0.0.0-20220725144611-272f38e5d71b // indirect
google.golang.org/protobuf v1.28.0 // indirect
gopkg.in/ini.v1 v1.66.6 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
gotest.tools v2.2.0+incompatible // indirect
honnef.co/go/tools v0.3.3 // indirect
mvdan.cc/gofumpt v0.3.1 // indirect
mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed // indirect
Expand Down
259 changes: 255 additions & 4 deletions go.sum

Large diffs are not rendered by default.

32 changes: 32 additions & 0 deletions test/loadtime/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
GOMOD="github.com/tendermint/tendermint/test/loadtime"
OUTPUT?=build/loadtime

build:
go build $(BUILD_FLAGS) -tags '$(BUILD_TAGS)' -o $(OUTPUT) .
.PHONY: build

check-proto-gen-deps:
ifeq (,$(shell which protoc))
$(error "protoc is required for Protobuf generation. See instructions for your platform on how to install it.")
endif
ifeq (,$(shell which protoc-gen-go))
$(error "protoc-gen-go is required for Protobuf generation. See instructions for your platform on how to install it.")
endif
.PHONY: check-proto-gen-deps

check-proto-format-deps:
ifeq (,$(shell which clang-format))
$(error "clang-format is required for Protobuf formatting. See instructions for your platform on how to install it.")
endif
.PHONY: check-proto-format-deps

proto-format: check-proto-format-deps
@echo "Formatting Protobuf files"
@find . -name '*.proto' -exec clang-format -i {} \;
.PHONY: proto-format

proto-gen: check-proto-gen-deps
@echo "Generating Protobuf files"
@find . -name '*.proto' -exec protoc \
--go_out=paths=source_relative:. {} \;
.PHONY: proto-gen
32 changes: 32 additions & 0 deletions test/loadtime/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# loadtime

This directory contains `loadtime`, a tool for generating transaction load against Tendermint.
`loadtime` generates transactions that contain the timestamp corresponding to when they were generated
as well as additional metadata to track the variables used when generating the load.


## Building loadtime

The `Makefile` contains a target for building the `loadtime` tool.

The following command will build the tool and place the resulting binary in `./build/loadtime`.

```bash
make build
```

## Use

`loadtime` leverages the [tm-load-test](https://github.com/informalsystems/tm-load-test)
framework. As a result, all flags and options specified on the `tm-load-test` apply to
`loadtime`.

Below is a basic invocation for generating load against a Tendermint websocket running
on `localhost:25567`

```bash
loadtime \
-c 1 -T 10 -r 1000 -s 1024 \
--broadcast-tx-method sync \
--endpoints ws://localhost:26657/websocket
```
11 changes: 11 additions & 0 deletions test/loadtime/basic.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#!/bin/sh

set -euo pipefail

# A basic invocation of the loadtime tool.

./build/loadtime \
-c 1 -T 10 -r 1000 -s 1024 \
--broadcast-tx-method sync \
--endpoints ws://localhost:26657/websocket

89 changes: 89 additions & 0 deletions test/loadtime/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package main

import (
"crypto/rand"
"fmt"

"github.com/informalsystems/tm-load-test/pkg/loadtest"
"github.com/tendermint/tendermint/test/loadtime/payload"
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/types/known/timestamppb"
)

// Ensure all of the interfaces are correctly satisfied.
var (
_ loadtest.ClientFactory = (*ClientFactory)(nil)
_ loadtest.Client = (*TxGenerator)(nil)
)

// ClientFactory implements the loadtest.ClientFactory interface.
type ClientFactory struct{}

// TxGenerator is responsible for generating transactions.
// TxGenerator holds the set of information that will be used to generate
// each transaction.
type TxGenerator struct {
conns uint64
rate uint64
size uint64
payloadSizeBytes uint64
}

func main() {
if err := loadtest.RegisterClientFactory("loadtime-client", &ClientFactory{}); err != nil {
panic(err)
}
loadtest.Run(&loadtest.CLIConfig{
AppName: "loadtime",
AppShortDesc: "Generate timestamped transaction load.",
AppLongDesc: "loadtime generates transaction load for the purpose of measuring the end-to-end latency of a transaction from submission to execution in a Tendermint network.", //nolint:lll
DefaultClientFactory: "loadtime-client",
})
}

func (f *ClientFactory) ValidateConfig(cfg loadtest.Config) error {
psb, err := payload.CalculateUnpaddedSizeBytes()
if err != nil {
return err
}

if psb > cfg.Size {
return fmt.Errorf("payload size exceeds configured size")
}
return nil
}

func (f *ClientFactory) NewClient(cfg loadtest.Config) (loadtest.Client, error) {
psb, err := payload.CalculateUnpaddedSizeBytes()
if err != nil {
return nil, err
}
return &TxGenerator{
conns: uint64(cfg.Connections),
rate: uint64(cfg.Rate),
size: uint64(cfg.Size),
payloadSizeBytes: uint64(psb),
}, nil
}

func (c *TxGenerator) GenerateTx() ([]byte, error) {
p := &payload.Payload{
Time: timestamppb.Now(),
Connections: c.conns,
Rate: c.rate,
Size: c.size,
Padding: make([]byte, c.size-c.payloadSizeBytes),
}
_, err := rand.Read(p.Padding)
if err != nil {
return nil, err
}
b, err := proto.Marshal(p)
if err != nil {
return nil, err
}

// prepend a single key so that the kv store only ever stores a single
// transaction instead of storing all tx and ballooning in size.
return append([]byte("a="), b...), nil
}
Loading

0 comments on commit f573d3d

Please sign in to comment.