-
Notifications
You must be signed in to change notification settings - Fork 292
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
test: add the loadtime tool (Backport #9342) (#9358)
* 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
1 parent
29c5a06
commit f573d3d
Showing
11 changed files
with
680 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} |
Oops, something went wrong.