Skip to content

Commit

Permalink
add comments, some review fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
kocubinski committed Dec 11, 2024
1 parent 0693d8c commit 91d4291
Show file tree
Hide file tree
Showing 12 changed files with 120 additions and 43 deletions.
5 changes: 5 additions & 0 deletions scripts/build/build.mk
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,11 @@ ifeq (bls12381,$(findstring bls12381,$(COSMOS_BUILD_OPTIONS)))
build_tags += bls12381
endif

# benchmark module
ifeq (benchmark,$(findstring benchmark,$(COSMOS_BUILD_OPTIONS)))
build_tags += benchmark
endif

whitespace :=
whitespace += $(whitespace)
comma := ,
Expand Down
19 changes: 2 additions & 17 deletions simapp/app_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import (
authmodulev1 "cosmossdk.io/api/cosmos/auth/module/v1"
authzmodulev1 "cosmossdk.io/api/cosmos/authz/module/v1"
bankmodulev1 "cosmossdk.io/api/cosmos/bank/module/v1"
benchmarkmodulev1 "cosmossdk.io/api/cosmos/benchmark/module/v1"
circuitmodulev1 "cosmossdk.io/api/cosmos/circuit/module/v1"
consensusmodulev1 "cosmossdk.io/api/cosmos/consensus/module/v1"
distrmodulev1 "cosmossdk.io/api/cosmos/distribution/module/v1"
Expand Down Expand Up @@ -109,7 +108,7 @@ var (
}

// application configuration (used by depinject)
appConfig = appconfig.Compose(&appv1alpha1.Config{
appConfig = &appv1alpha1.Config{
Modules: []*appv1alpha1.ModuleConfig{
{
Name: runtime.ModuleName,
Expand Down Expand Up @@ -299,20 +298,6 @@ var (
Name: bankv2types.ModuleName,
Config: appconfig.WrapAny(&bankmodulev2.Module{}),
},
{
Name: benchmark.ModuleName,
Config: appconfig.WrapAny(&benchmarkmodulev1.Module{
GenesisParams: &benchmarkmodulev1.GeneratorParams{
Seed: 34,
BucketCount: 1,
GenesisCount: 100,
KeyMean: 64,
KeyStdDev: 12,
ValueMean: 1024,
ValueStdDev: 256,
},
}),
},
},
})
}
)
3 changes: 2 additions & 1 deletion simapp/app_di.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"cosmossdk.io/core/registry"
corestore "cosmossdk.io/core/store"
"cosmossdk.io/depinject"
"cosmossdk.io/depinject/appconfig"
_ "cosmossdk.io/indexer/postgres" // register the postgres indexer
"cosmossdk.io/log"
"cosmossdk.io/x/accounts"
Expand Down Expand Up @@ -96,7 +97,7 @@ func init() {
// AppConfig returns the default app config.
func AppConfig() depinject.Config {
return depinject.Configs(
appConfig, // Alternatively use appconfig.LoadYAML(AppConfigYAML)
appconfig.Compose(appConfig), // Alternatively use appconfig.LoadYAML(AppConfigYAML)
depinject.Provide(
ProvideExampleMintFn, // optional: override the mint module's mint function with epoched minting
),
Expand Down
30 changes: 30 additions & 0 deletions simapp/benchmark.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
//go:build benchmark

package simapp

import (
appv1alpha1 "cosmossdk.io/api/cosmos/app/v1alpha1"
benchmarkmodulev1 "cosmossdk.io/api/cosmos/benchmark/module/v1"
"cosmossdk.io/depinject/appconfig"
benchmark "cosmossdk.io/tools/benchmark/module"
)

func init() {
// WARNING!
// Enabling this module will produce 3M keys in the genesis state for the benchmark module.
// Will also enable processing of benchmark transactions which can easily overwhelm the system.
appConfig.Modules = append(appConfig.Modules, &appv1alpha1.ModuleConfig{
Name: benchmark.ModuleName,
Config: appconfig.WrapAny(&benchmarkmodulev1.Module{
GenesisParams: &benchmarkmodulev1.GeneratorParams{
Seed: 34,
BucketCount: 3,
GenesisCount: 3_000_000,
KeyMean: 64,
KeyStdDev: 12,
ValueMean: 1024,
ValueStdDev: 256,
},
}),
})
}
19 changes: 2 additions & 17 deletions simapp/v2/app_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import (
authmodulev1 "cosmossdk.io/api/cosmos/auth/module/v1"
authzmodulev1 "cosmossdk.io/api/cosmos/authz/module/v1"
bankmodulev1 "cosmossdk.io/api/cosmos/bank/module/v1"
benchmarkmodulev1 "cosmossdk.io/api/cosmos/benchmark/module/v1"
circuitmodulev1 "cosmossdk.io/api/cosmos/circuit/module/v1"
consensusmodulev1 "cosmossdk.io/api/cosmos/consensus/module/v1"
distrmodulev1 "cosmossdk.io/api/cosmos/distribution/module/v1"
Expand Down Expand Up @@ -109,7 +108,7 @@ var (
}

// ModuleConfig is the application module configuration used by depinject
ModuleConfig = appconfig.Compose(&appv1alpha1.Config{
ModuleConfig = &appv1alpha1.Config{
Modules: []*appv1alpha1.ModuleConfig{
{
Name: runtime.ModuleName,
Expand Down Expand Up @@ -304,20 +303,6 @@ var (
Name: bankv2types.ModuleName,
Config: appconfig.WrapAny(&bankmodulev2.Module{}),
},
{
Name: benchmark.ModuleName,
Config: appconfig.WrapAny(&benchmarkmodulev1.Module{
GenesisParams: &benchmarkmodulev1.GeneratorParams{
Seed: 34,
BucketCount: 1,
GenesisCount: 100,
KeyMean: 64,
KeyStdDev: 12,
ValueMean: 1024,
ValueStdDev: 256,
},
}),
},
},
})
}
)
3 changes: 2 additions & 1 deletion simapp/v2/app_di.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"cosmossdk.io/core/server"
"cosmossdk.io/core/transaction"
"cosmossdk.io/depinject"
"cosmossdk.io/depinject/appconfig"
_ "cosmossdk.io/indexer/postgres" // register the postgres indexer
"cosmossdk.io/log"
"cosmossdk.io/runtime/v2"
Expand Down Expand Up @@ -49,7 +50,7 @@ type SimApp[T transaction.Tx] struct {
// AppConfig returns the default app config.
func AppConfig() depinject.Config {
return depinject.Configs(
ModuleConfig, // Alternatively use appconfig.LoadYAML(AppConfigYAML)
appconfig.Compose(ModuleConfig), // Alternatively use appconfig.LoadYAML(AppConfigYAML)
runtime.DefaultServiceBindings(),
codec.DefaultProviders,
depinject.Provide(
Expand Down
30 changes: 30 additions & 0 deletions simapp/v2/benchmark.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
//go:build benchmark

package simapp

import (
appv1alpha1 "cosmossdk.io/api/cosmos/app/v1alpha1"
benchmarkmodulev1 "cosmossdk.io/api/cosmos/benchmark/module/v1"
"cosmossdk.io/depinject/appconfig"
benchmark "cosmossdk.io/tools/benchmark/module"
)

func init() {
// WARNING!
// Enabling this module will produce 3M keys in the genesis state for the benchmark module.
// Will also enable processing of benchmark transactions which can easily overwhelm the system.
ModuleConfig.Modules = append(ModuleConfig.Modules, &appv1alpha1.ModuleConfig{
Name: benchmark.ModuleName,
Config: appconfig.WrapAny(&benchmarkmodulev1.Module{
GenesisParams: &benchmarkmodulev1.GeneratorParams{
Seed: 34,
BucketCount: 3,
GenesisCount: 3_000_000,
KeyMean: 64,
KeyStdDev: 12,
ValueMean: 1024,
ValueStdDev: 256,
},
}),
})
}
35 changes: 34 additions & 1 deletion tools/benchmark/generator/gen.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"cosmossdk.io/tools/benchmark"
)

// Options is the configuration for the generator.
type Options struct {
*module.GeneratorParams
// HomeDir is for reading/writing state
Expand All @@ -27,6 +28,8 @@ type Options struct {
DeleteWeight float64
}

// State is the state of the generator.
// It can be marshaled and unmarshaled to/from a binary format.
type State struct {
Src interface {
rand.Source
Expand All @@ -36,6 +39,7 @@ type State struct {
Keys [][]Payload
}

// Marshal writes the state to w.
func (s *State) Marshal(w io.Writer) error {
srcBz, err := s.Src.MarshalBinary()
if err != nil {
Expand Down Expand Up @@ -65,6 +69,7 @@ func (s *State) Marshal(w io.Writer) error {
return nil
}

// Unmarshal reads the state from r.
func (s *State) Unmarshal(r io.Reader) error {
srcBz := make([]byte, 20)
if _, err := r.Read(srcBz); err != nil {
Expand Down Expand Up @@ -95,6 +100,9 @@ func (s *State) Unmarshal(r io.Reader) error {
return nil
}

// Generator generates operations for a benchmark transaction.
// The generator is stateful, keeping track of which keys have been inserted
// so that meaningful gets and deletes can be generated.
type Generator struct {
Options

Expand All @@ -104,6 +112,7 @@ type Generator struct {

type opt func(*Generator)

// NewGenerator creates a new generator with the given options.
func NewGenerator(opts Options, f ...opt) *Generator {
g := &Generator{
Options: opts,
Expand All @@ -118,6 +127,9 @@ func NewGenerator(opts Options, f ...opt) *Generator {
return g
}

// WithGenesis sets the generator state to the genesis seed.
// When the generator is created, it will sync to genesis state.
// The benchmark client needs to do this so that it can generate meaningful tx operations.
func WithGenesis() func(*Generator) {
return func(g *Generator) {
// sync state to genesis seed
Expand All @@ -130,13 +142,15 @@ func WithGenesis() func(*Generator) {
}
}

// WithSeed sets the seed for the generator.
func WithSeed(seed uint64) func(*Generator) {
return func(g *Generator) {
g.state.Src = rand.NewPCG(seed, seed>>32)
g.rand = rand.New(g.state.Src)
}
}

// Load loads the generator state from disk.
func (g *Generator) Load() error {
f := fmt.Sprintf("%s/data/generator_state.bin", g.HomeDir)
r, err := os.Open(f)
Expand All @@ -149,16 +163,22 @@ func (g *Generator) Load() error {
return g.state.Unmarshal(r)
}

// Payload is a 2-tuple of seed and length.
// A seed is uint64 which is used to generate a byte slice of size length.
type Payload [2]uint64

// Seed returns the seed in the payload.
func (p Payload) Seed() uint64 {
return p[0]
}

// Length returns the length in the payload.
func (p Payload) Length() uint64 {
return p[1]
}

// Bytes returns the byte slice generated from the seed and length.
// The underlying byte slice is deterministically generated using the (very fast) xxhash algorithm.
func (p Payload) Bytes() []byte {
return Bytes(p.Seed(), p.Length())
}
Expand All @@ -171,6 +191,7 @@ func NewPayload(seed, length uint64) Payload {
return Payload{seed, length}
}

// KV is a key-value pair with a store key.
type KV struct {
StoreKey uint64
Key Payload
Expand All @@ -194,6 +215,9 @@ func (g *Generator) setKey(bucket uint64, payload Payload) {
g.state.Keys[bucket] = append(g.state.Keys[bucket], payload)
}

// GenesisSet returns a sequence of key-value pairs for the genesis state.
// It is called by the server during InitGenesis to generate and set the initial state.
// The client uses WithGenesis to sync to the genesis state.
func (g *Generator) GenesisSet() iter.Seq[*KV] {
return func(yield func(*KV) bool) {
for range g.GenesisCount {
Expand All @@ -209,9 +233,12 @@ func (g *Generator) GenesisSet() iter.Seq[*KV] {
}
}

// Next generates the next benchmark operation.
// The operation is one of insert, update, get, or delete.
// The tx client calls this function to deterministically generate the next operation.
func (g *Generator) Next() (uint64, *benchmark.Op, error) {
if g.InsertWeight+g.UpdateWeight+g.GetWeight+g.DeleteWeight != 1 {

Check notice

Code scanning / CodeQL

Floating point arithmetic Note test

Floating point arithmetic operations are not associative and a possible source of non-determinism

Check notice

Code scanning / CodeQL

Floating point arithmetic Note test

Floating point arithmetic operations are not associative and a possible source of non-determinism

Check notice

Code scanning / CodeQL

Floating point arithmetic Note test

Floating point arithmetic operations are not associative and a possible source of non-determinism
return 0, nil, fmt.Errorf("probabilities must sum to 1")
return 0, nil, fmt.Errorf("weights must sum to 1")
}

var (
Expand Down Expand Up @@ -265,6 +292,7 @@ func (g *Generator) Next() (uint64, *benchmark.Op, error) {
return bucket, op, nil
}

// NormUint64 returns a random uint64 with a normal distribution.
func (g *Generator) NormUint64(mean, stdDev uint64) uint64 {
return uint64(g.rand.NormFloat64()*float64(stdDev) + float64(mean))

Check notice

Code scanning / CodeQL

Floating point arithmetic Note test

Floating point arithmetic operations are not associative and a possible source of non-determinism

Check notice

Code scanning / CodeQL

Floating point arithmetic Note test

Floating point arithmetic operations are not associative and a possible source of non-determinism
}
Expand All @@ -277,6 +305,7 @@ func (g *Generator) getLength(mean, stdDev uint64) uint64 {
return length
}

// UintN returns a random uint64 in the range [0, n).
func (g *Generator) UintN(n uint64) uint64 {
return g.rand.Uint64N(n)
}
Expand Down Expand Up @@ -305,6 +334,7 @@ func encodeUint64(x uint64) []byte {

const maxStoreKeyGenIterations = 100

// StoreKeys deterministically generates a set of unique store keys from seed.
func StoreKeys(prefix string, seed, count uint64) ([]string, error) {
r := rand.New(rand.NewPCG(seed, seed>>32))
keys := make([]string, count)
Expand All @@ -323,10 +353,13 @@ func StoreKeys(prefix string, seed, count uint64) ([]string, error) {
keys[i] = sk
seen[sk] = struct{}{}
i++
j++
}
return keys, nil
}

// Bytes generates a byte slice of length length from seed.
// The byte slice is deterministically generated using the (very fast) xxhash algorithm.
func Bytes(seed, length uint64) []byte {
b := make([]byte, length)
rounds := length / 8
Expand Down
1 change: 0 additions & 1 deletion tools/benchmark/module/depinject.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ const ModuleName = "benchmark"
const maxStoreKeyGenIterations = 100

func init() {
// TODO try depinject gogo API
appconfig.RegisterModule(
&modulev1.Module{},
appconfig.Provide(
Expand Down
5 changes: 1 addition & 4 deletions tools/benchmark/module/module.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ package module
import (
"context"
"encoding/json"
"fmt"

"github.com/cosmos/cosmos-sdk/types/msgservice"
"github.com/grpc-ecosystem/grpc-gateway/runtime"
"github.com/spf13/cobra"
Expand Down Expand Up @@ -67,8 +65,7 @@ func (a *AppModule) InitGenesis(ctx context.Context, _ json.RawMessage) error {
for kv := range g.GenesisSet() {
i++
if i%100_000 == 0 {
fmt.Printf("init genesis: %d/%d\n", i, a.genesisParams.GenesisCount)
a.log.Warn("init genesis", "progress", i, "total", a.genesisParams.GenesisCount)
a.log.Warn("benchmark: init genesis", "progress", i, "total", a.genesisParams.GenesisCount)
}
sk := a.storeKeys[kv.StoreKey]
key := gen.Bytes(kv.Key.Seed(), kv.Key.Length())
Expand Down
2 changes: 1 addition & 1 deletion tools/benchmark/proto/buf.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
version: v1
name: buf.build/mods/consensus
name: buf.build/mods/benchmark
deps:
- buf.build/cosmos/cosmos-sdk # pin the Cosmos SDK version
- buf.build/cometbft/cometbft:4a62c99d422068a5165429b62a7eb824df46cca9 # CometBFT v0.38
Expand Down
Loading

0 comments on commit 91d4291

Please sign in to comment.