Documentation
¶
Index ¶
- Constants
- func Clip[T constraints.Ordered](value, low, high T) T
- func CreateConfigBlock(policy *PolicyProfile) (*common.Block, error)
- func CreateConfigEnvelope(policy *PolicyProfile) ([]byte, error)
- func CreateConfigTx(policy *PolicyProfile) (*protoblocktx.Tx, error)
- func CreateDefaultConfigBlock(conf *ConfigBlock) (*common.Block, error)
- func CreateNamespacesTX(policy *PolicyProfile) (*protoblocktx.Tx, error)
- func GenerateArray[G Generator[T], T any](g G, size int) []T
- func GenerateTransactions(tb testing.TB, p *Profile, count int) []*protoblocktx.Tx
- func Map[T, K any](arr []T, mapper func(index int, value T) K) []K
- func MeanStd[T constraints.Float](arr []T) (mean, std float64)
- func Must(err error)
- func NewLimiter(c *LimiterConfig, burst int) *rate.Limiter
- func NewRandFromSeedGenerator(seedRnd *rand.Rand) *rand.Rand
- func Sum[T constraints.Float](arr []T) float64
- func SumInt[T constraints.Integer](arr []T) int64
- type BernoulliGenerator
- type BlockProfile
- type ByteArrayGenerator
- type ConfigBlock
- type ConflictProfile
- type ConstGenerator
- type DependencyDescription
- type DiscreteGenerator
- type DiscreteValue
- type Distribution
- func NewBernoulliDistribution(probability Probability) *Distribution
- func NewConstantDistribution(value float64) *Distribution
- func NewDiscreteDistribution(values []DiscreteValue[float64]) *Distribution
- func NewNormalDistribution(mean, std float64) *Distribution
- func NewUniformDistribution(minVal, maxVal float64) *Distribution
- func (d *Distribution) MakeBooleanGenerator(rnd *rand.Rand) *FloatToBooleanGenerator
- func (d *Distribution) MakeGenerator(rnd *rand.Rand) Generator[float64]
- func (d *Distribution) MakeIntGenerator(rnd *rand.Rand) *FloatToIntGenerator
- func (d *Distribution) MakePositiveIntGenerator(rnd *rand.Rand) *FloatToPositiveIntGenerator
- type FloatToBooleanGenerator
- type FloatToIntGenerator
- type FloatToPositiveIntGenerator
- type Generator
- type HashSignerVerifier
- func (e *HashSignerVerifier) GetVerificationKeyAndSigner() (signature.PublicKey, *sigtest.NsSigner)
- func (e *HashSignerVerifier) GetVerificationPolicy() *protoblocktx.NamespacePolicy
- func (e *HashSignerVerifier) Sign(tx *protoblocktx.Tx, nsIndex int) signature.Signature
- func (e *HashSignerVerifier) Verify(tx *protoblocktx.Tx, nsIndex int) bool
- type IndependentTxGenerator
- type Key
- type KeyPath
- type KeyProfile
- type LimiterConfig
- type Modifier
- type MultiGenerator
- type NormalDist
- type NormalGenerator
- type Policy
- type PolicyProfile
- type Probability
- type Profile
- type QueryGenerator
- type QueryProfile
- type QueryStream
- type RateLimiterGenerator
- type StreamOptions
- type StreamWithSetup
- type TransactionProfile
- type TxGeneratorWithSetup
- type TxSignerVerifier
- type TxStream
- type UUIDGenerator
- type UniformDist
- type UniformGenerator
Constants ¶
const ( DependencyReadOnly = "read" DependencyReadWrite = "read-write" DependencyBlindWrite = "write" )
Dependency types.
const GeneratedNamespaceID = "0"
GeneratedNamespaceID for now we're only generating transactions for a single namespace.
Variables ¶
This section is empty.
Functions ¶
func Clip ¶
func Clip[T constraints.Ordered](value, low, high T) T
Clip returns the given value, clipped between the given boundaries.
func CreateConfigBlock ¶
func CreateConfigBlock(policy *PolicyProfile) (*common.Block, error)
CreateConfigBlock creating a config block.
func CreateConfigEnvelope ¶
func CreateConfigEnvelope(policy *PolicyProfile) ([]byte, error)
CreateConfigEnvelope creating a meta policy.
func CreateConfigTx ¶
func CreateConfigTx(policy *PolicyProfile) (*protoblocktx.Tx, error)
CreateConfigTx creating a config TX.
func CreateDefaultConfigBlock ¶
func CreateDefaultConfigBlock(conf *ConfigBlock) (*common.Block, error)
CreateDefaultConfigBlock creates a config block with default values.
func CreateNamespacesTX ¶
func CreateNamespacesTX(policy *PolicyProfile) (*protoblocktx.Tx, error)
CreateNamespacesTX creating the transaction containing the requested namespaces into the MetaNamespace.
func GenerateArray ¶
GenerateArray generates an array of items of the requested size given a generator.
func GenerateTransactions ¶ added in v0.1.4
GenerateTransactions is used for benchmarking.
func MeanStd ¶
func MeanStd[T constraints.Float](arr []T) (mean, std float64)
MeanStd returns the mean and std of an array of float samples.
func NewLimiter ¶
func NewLimiter(c *LimiterConfig, burst int) *rate.Limiter
NewLimiter instantiate a new rate limiter with optional remote control capabilities.
func NewRandFromSeedGenerator ¶
NewRandFromSeedGenerator creates a new random generator using a generated seed.
func Sum ¶
func Sum[T constraints.Float](arr []T) float64
Sum returns the sum of an array of floats.
func SumInt ¶
func SumInt[T constraints.Integer](arr []T) int64
SumInt returns the sum of an array of integers.
Types ¶
type BernoulliGenerator ¶
type BernoulliGenerator struct {
Rnd *rand.Rand
Probability Probability
}
BernoulliGenerator generates 1 with probability of p.
func (*BernoulliGenerator) Next ¶
func (d *BernoulliGenerator) Next() float64
Next yields the next bernoulli value.
type BlockProfile ¶
type BlockProfile struct {
// Size of the block
Size uint64 `mapstructure:"size" yaml:"size"`
}
BlockProfile describes generate block characteristics.
type ByteArrayGenerator ¶
ByteArrayGenerator generates a random byte array of Size.
func (*ByteArrayGenerator) Next ¶
func (g *ByteArrayGenerator) Next() []byte
Next yields a byte array.
type ConfigBlock ¶
type ConfigBlock struct {
ChannelID string
OrdererEndpoints []*connection.OrdererEndpoint
MetaNamespaceVerificationKey []byte
}
ConfigBlock represents the configuration of the config block.
type ConflictProfile ¶
type ConflictProfile struct {
// Probability of invalid signatures [0,1] (default: 0)
InvalidSignatures Probability `mapstructure:"invalid-signatures" yaml:"invalid-signatures"`
// Dependencies list of dependencies
Dependencies []DependencyDescription `mapstructure:"dependencies" yaml:"dependencies"`
}
ConflictProfile describes the TX conflict characteristics. Note that each of the conflicts' probabilities are independent bernoulli distributions.
type ConstGenerator ¶
type ConstGenerator[T any] struct { Const T }
ConstGenerator produces a constant value.
func (*ConstGenerator[T]) Next ¶
func (g *ConstGenerator[T]) Next() T
Next yields the constant value.
type DependencyDescription ¶
type DependencyDescription struct {
// Probability of the dependency type [0,1] (default: 0)
Probability Probability `mapstructure:"probability" yaml:"probability"`
// Gap is the distance between the dependent TXs (default: 1)
Gap *Distribution `mapstructure:"gap" yaml:"gap"`
// Src dependency "read", "write", or "read-write"
Src string `mapstructure:"src" yaml:"src"`
// Dst dependency "read", "write", or "read-write"
Dst string `mapstructure:"dst" yaml:"dst"`
}
DependencyDescription describes a dependency type.
type DiscreteGenerator ¶
type DiscreteGenerator[T any] struct { Rnd *rand.Rand Values []DiscreteValue[T] }
DiscreteGenerator generates values with a discrete distribution.
func (*DiscreteGenerator[T]) Next ¶
func (d *DiscreteGenerator[T]) Next() T
Next yields the next discrete value.
type DiscreteValue ¶
type DiscreteValue[T any] struct { Value T `mapstructure:"value"` Probability Probability `mapstructure:"probability"` }
DiscreteValue describe the appearance probability of a value.
type Distribution ¶
type Distribution struct {
Const float64 `mapstructure:"const" yaml:"const,omitempty"`
Uniform *UniformDist `mapstructure:"uniform" yaml:"uniform,omitempty"`
Normal *NormalDist `mapstructure:"normal" yaml:"normal,omitempty"`
Bernoulli Probability `mapstructure:"bernoulli" yaml:"bernoulli,omitempty"`
Discrete []DiscreteValue[float64] `mapstructure:"discrete" yaml:"discrete,omitempty"`
}
Distribution descriptor for the available distributions.
func NewBernoulliDistribution ¶
func NewBernoulliDistribution(probability Probability) *Distribution
NewBernoulliDistribution creates a Bernoulli distribution.
func NewConstantDistribution ¶
func NewConstantDistribution(value float64) *Distribution
NewConstantDistribution creates a constant value distribution.
func NewDiscreteDistribution ¶
func NewDiscreteDistribution(values []DiscreteValue[float64]) *Distribution
NewDiscreteDistribution creates a discrete distribution.
func NewNormalDistribution ¶
func NewNormalDistribution(mean, std float64) *Distribution
NewNormalDistribution creates a normal distribution.
func NewUniformDistribution ¶
func NewUniformDistribution(minVal, maxVal float64) *Distribution
NewUniformDistribution creates a uniform distribution.
func (*Distribution) MakeBooleanGenerator ¶
func (d *Distribution) MakeBooleanGenerator(rnd *rand.Rand) *FloatToBooleanGenerator
MakeBooleanGenerator returns a new boolean generator according to the distribution description.
func (*Distribution) MakeGenerator ¶
func (d *Distribution) MakeGenerator(rnd *rand.Rand) Generator[float64]
MakeGenerator returns a new generator according to the distribution description. The default distribution is const=0.
func (*Distribution) MakeIntGenerator ¶
func (d *Distribution) MakeIntGenerator(rnd *rand.Rand) *FloatToIntGenerator
MakeIntGenerator returns a new integer generator according to the distribution description.
func (*Distribution) MakePositiveIntGenerator ¶
func (d *Distribution) MakePositiveIntGenerator(rnd *rand.Rand) *FloatToPositiveIntGenerator
MakePositiveIntGenerator returns a new positive (>=1) integer generator according to the distribution description.
type FloatToBooleanGenerator ¶
FloatToBooleanGenerator wraps a float generator and produces boolean (true when >=1).
func (*FloatToBooleanGenerator) Next ¶
func (g *FloatToBooleanGenerator) Next() bool
Next yields a new integer.
type FloatToIntGenerator ¶
FloatToIntGenerator wraps a float generator and produces integers.
func (*FloatToIntGenerator) Next ¶
func (g *FloatToIntGenerator) Next() int
Next yields a new integer.
type FloatToPositiveIntGenerator ¶
FloatToPositiveIntGenerator wraps a float generator and produces positive int (>=1).
func (*FloatToPositiveIntGenerator) Next ¶
func (g *FloatToPositiveIntGenerator) Next() uint64
Next yields a new integer.
type Generator ¶
type Generator[T any] interface { Next() T }
Generator generates new T each time Next() is called.
type HashSignerVerifier ¶
type HashSignerVerifier struct {
// contains filtered or unexported fields
}
HashSignerVerifier supports signing and verifying a hash value.
func NewHashSignerVerifier ¶
func NewHashSignerVerifier(profile *Policy) *HashSignerVerifier
NewHashSignerVerifier creates a new HashSignerVerifier given a workload profile and a seed.
func (*HashSignerVerifier) GetVerificationKeyAndSigner ¶
func (e *HashSignerVerifier) GetVerificationKeyAndSigner() (signature.PublicKey, *sigtest.NsSigner)
GetVerificationKeyAndSigner returns the verification key and the signer.
func (*HashSignerVerifier) GetVerificationPolicy ¶
func (e *HashSignerVerifier) GetVerificationPolicy() *protoblocktx.NamespacePolicy
GetVerificationPolicy returns the verification policy.
func (*HashSignerVerifier) Sign ¶
func (e *HashSignerVerifier) Sign(tx *protoblocktx.Tx, nsIndex int) signature.Signature
Sign signs a hash.
func (*HashSignerVerifier) Verify ¶
func (e *HashSignerVerifier) Verify(tx *protoblocktx.Tx, nsIndex int) bool
Verify verifies a Signature.
type IndependentTxGenerator ¶
type IndependentTxGenerator struct {
TxIDGenerator *UUIDGenerator
ReadOnlyKeyGenerator *MultiGenerator[Key]
ReadWriteKeyGenerator *MultiGenerator[Key]
BlindWriteKeyGenerator *MultiGenerator[Key]
ReadWriteValueGenerator *ByteArrayGenerator
BlindWriteValueGenerator *ByteArrayGenerator
}
IndependentTxGenerator generates a new valid TX given key generators.
func (*IndependentTxGenerator) Next ¶
func (g *IndependentTxGenerator) Next() *protoblocktx.Tx
Next generate a new TX.
type KeyPath ¶
type KeyPath struct {
SigningKey string `mapstructure:"signing-key" yaml:"signing-key"`
VerificationKey string `mapstructure:"verification-key" yaml:"verification-key"`
SignCertificate string `mapstructure:"sign-certificate" yaml:"sign-certificate"`
}
KeyPath describes how to find/generate the signature keys.
type KeyProfile ¶
type KeyProfile struct {
// Size is the size of the key to generate.
Size uint32 `mapstructure:"size" yaml:"size"`
}
KeyProfile describes generated keys characteristics.
type LimiterConfig ¶
type LimiterConfig struct {
InitialLimit rate.Limit `mapstructure:"initial-limit"`
// Endpoint for a simple http server to set the limiter.
Endpoint connection.Endpoint `mapstructure:"endpoint"`
}
LimiterConfig is used to create a limiter.
type Modifier ¶
type Modifier interface {
Modify(*protoblocktx.Tx) (*protoblocktx.Tx, error)
}
Modifier modifies a TX.
type MultiGenerator ¶
MultiGenerator generates an array of size determined by Count, with items generated by Gen.
func (*MultiGenerator[T]) Next ¶
func (g *MultiGenerator[T]) Next() []T
Next yields an array of items.
type NormalDist ¶
type NormalDist struct {
Mean float64 `mapstructure:"mean" yaml:"mean,omitempty"`
Std float64 `mapstructure:"std" yaml:"std,omitempty"`
}
NormalDist describes normal.
type NormalGenerator ¶
NormalGenerator generates values with a normal distribution.
func (*NormalGenerator) Next ¶
func (d *NormalGenerator) Next() float64
Next yields the next normal value.
type Policy ¶
type Policy struct {
Scheme signature.Scheme `mapstructure:"scheme" yaml:"scheme"`
Seed int64 `mapstructure:"seed" yaml:"seed"`
// KeyPath describes how to find/generate the signature keys.
// KeyPath is still not supported.
KeyPath *KeyPath `mapstructure:"key-path" yaml:"key-path"`
}
Policy describes how to sign/verify a TX.
type PolicyProfile ¶
type PolicyProfile struct {
// NamespacePolicies specifies the namespace policies.
NamespacePolicies map[string]*Policy `mapstructure:"namespace-policies" yaml:"namespace-policies"`
// OrdererEndpoints may specify the endpoints to add to the config block.
// If this field is empty, no endpoints will be configured.
// If ConfigBlockPath is specified, this value is ignored.
OrdererEndpoints []*connection.OrdererEndpoint `mapstructure:"orderer-endpoints" yaml:"orderer-endpoints"`
// ConfigBlockPath may specify the config block to use.
// If this field is empty, a default config block will be generated.
ConfigBlockPath string `mapstructure:"config-block-path" yaml:"config-block-path"`
}
PolicyProfile holds the policy information for the load generation.
type Probability ¶
type Probability = float64
Probability is a float in the closed interval [0,1].
const ( // Always is 100%. Always Probability = 1 // Never is 0%. Never Probability = 0 )
type Profile ¶
type Profile struct {
Block BlockProfile `mapstructure:"block" yaml:"block"`
Key KeyProfile `mapstructure:"key" yaml:"key"`
Transaction TransactionProfile `mapstructure:"transaction" yaml:"transaction"`
Query QueryProfile `mapstructure:"query" yaml:"query"`
Conflicts ConflictProfile `mapstructure:"conflicts" yaml:"conflicts"`
// The seed to generate the seeds for each worker
Seed int64 `mapstructure:"seed" yaml:"seed"`
// Workers is the number of independent producers.
// Each worker uses a unique seed that is generated from the main seed.
// To ensure responsibility of items between runs (e.g., for query)
// the number of workers must be preserved.
Workers uint32 `mapstructure:"workers" yaml:"workers"`
}
Profile describes the generated workload characteristics. It only contains parameters that deterministically affect the generated items. The items order, however, might be affected by other parameters.
func DefaultProfile ¶
DefaultProfile is used for testing and benchmarking.
type QueryGenerator ¶
type QueryGenerator struct {
ValidKeyGenerator *ByteArrayGenerator
InvalidKeyGenerator *ByteArrayGenerator
Size Generator[int]
InvalidPortion Generator[float64]
ShuffleRnd *rand.Rand
Shuffle bool
}
QueryGenerator generates a new query for keys.
func (*QueryGenerator) Next ¶
func (g *QueryGenerator) Next() *protoqueryservice.Query
Next generate a new query.
type QueryProfile ¶
type QueryProfile struct {
// The number of keys to query.
QuerySize *Distribution `mapstructure:"query-size" yaml:"query-size"`
// The minimal portion of invalid keys (1 => all keys are invalid).
// This is a lower bound since some valid keys might have failed to commit due to conflicts.
MinInvalidKeysPortion *Distribution `mapstructure:"min-invalid-keys-portion" yaml:"min-invalid-keys-portion"`
// If Shuffle=false, the valid keys will be placed first.
// Otherwise, they will be shuffled.
Shuffle bool `mapstructure:"shuffle" yaml:"shuffle"`
}
QueryProfile describes generate query characteristics.
type QueryStream ¶
type QueryStream struct {
// contains filtered or unexported fields
}
QueryStream generates stream's queries consumers.
func NewQueryGenerator ¶
func NewQueryGenerator(profile *Profile, options *StreamOptions) *QueryStream
NewQueryGenerator creates workers that generates queries into a queue.
func (*QueryStream) MakeGenerator ¶
func (s *QueryStream) MakeGenerator() *RateLimiterGenerator[*protoqueryservice.Query]
MakeGenerator creates a new generator that consumes from the stream. Each generator must be used from a single goroutine, but different generators from the same Stream can be used concurrently.
type RateLimiterGenerator ¶
type RateLimiterGenerator[T any] struct { Chan <-chan []T Limiter *rate.Limiter // contains filtered or unexported fields }
RateLimiterGenerator pull batch of values from Chan and yield them one by one. It limits the generated rate using Limiter. It will finish once Chan is closed.
func StartGenerator ¶
func StartGenerator(tb testing.TB, p *Profile) *RateLimiterGenerator[*protoblocktx.Tx]
StartGenerator is used for benchmarking.
func (*RateLimiterGenerator[T]) Next ¶
func (g *RateLimiterGenerator[T]) Next(ctx context.Context) T
Next yields a value at the required rate.
type StreamOptions ¶
type StreamOptions struct {
// RateLimit directly impacts the rate by limiting it.
RateLimit *LimiterConfig `mapstructure:"rate-limit" yaml:"rate-limit"`
// GenBatch impacts the rate by batching generated items before inserting then the channel.
// This helps overcome the inherit rate limitation of Go channels.
GenBatch uint32 `mapstructure:"gen-batch" yaml:"gen-batch"`
// BuffersSize impact the rate by masking fluctuation in performance.
BuffersSize int `mapstructure:"buffers-size" yaml:"buffers-size"`
}
StreamOptions allows adjustment to the stream rate. It only contains parameters that do not affect the produced items. However, these parameters might affect the order of the items.
func (*StreamOptions) Debug ¶
func (o *StreamOptions) Debug()
Debug outputs the stream configuration to stdout.
type StreamWithSetup ¶
type StreamWithSetup struct {
WorkloadSetupTXs channel.Reader[*protoblocktx.Tx]
TxStream *TxStream
BlockSize uint64
}
StreamWithSetup implements the TxStream interface.
func (*StreamWithSetup) MakeTxGenerator ¶
func (c *StreamWithSetup) MakeTxGenerator() *TxGeneratorWithSetup
MakeTxGenerator instantiate clientTxGenerator.
type TransactionProfile ¶
type TransactionProfile struct {
// The sizes of the values to generate (size=0 => value=nil)
ReadWriteValueSize uint32 `mapstructure:"read-write-value-size" yaml:"read-write-value-size"`
BlindWriteValueSize uint32 `mapstructure:"blind-write-value-size" yaml:"blind-write-value-size"`
// The number of keys to generate (read ver=nil)
ReadOnlyCount *Distribution `mapstructure:"read-only-count" yaml:"read-only-count"`
// The number of keys to generate (read ver=nil/write)
ReadWriteCount *Distribution `mapstructure:"read-write-count" yaml:"read-write-count"`
// The number of keys to generate (write)
BlindWriteCount *Distribution `mapstructure:"write-count" yaml:"write-count"`
Policy *PolicyProfile `mapstructure:"policy" yaml:"policy"`
}
TransactionProfile describes generate TX characteristics.
type TxGeneratorWithSetup ¶
type TxGeneratorWithSetup struct {
WorkloadSetupTXs channel.Reader[*protoblocktx.Tx]
TxGen *RateLimiterGenerator[*protoblocktx.Tx]
}
TxGeneratorWithSetup is a TX generator that first submit TXs from the WorkloadSetupTXs, and blocks until indicated that it was committed. Then, it submits transactions from the tx stream.
func (*TxGeneratorWithSetup) Next ¶
func (g *TxGeneratorWithSetup) Next(ctx context.Context, size int) []*protoblocktx.Tx
Next generate the next TX.
type TxSignerVerifier ¶
type TxSignerVerifier struct {
HashSigners map[string]*HashSignerVerifier
}
TxSignerVerifier supports signing and verifying a TX, given a hash signer.
func NewTxSignerVerifier ¶
func NewTxSignerVerifier(policy *PolicyProfile) *TxSignerVerifier
NewTxSignerVerifier creates a new TxSignerVerifier given a workload profile.
func (*TxSignerVerifier) Sign ¶
func (e *TxSignerVerifier) Sign(tx *protoblocktx.Tx)
Sign signs a TX.
func (*TxSignerVerifier) Verify ¶
func (e *TxSignerVerifier) Verify(tx *protoblocktx.Tx) bool
Verify verifies a signature on the transaction.
type TxStream ¶
type TxStream struct {
// contains filtered or unexported fields
}
TxStream yields transactions from the stream.
func NewTxStream ¶
func NewTxStream( profile *Profile, options *StreamOptions, modifierGenerators ...Generator[Modifier], ) *TxStream
NewTxStream creates workers that generates transactions into a queue and apply the modifiers. Each worker will have a unique instance of the modifier to avoid concurrency issues. The modifiers will be applied in the order they are given. A transaction modifier can modify any of its fields to adjust the workload. For example, a modifier can query the database for the read-set versions to simulate a real transaction. The signature modifier is applied last so all previous modifications will be signed correctly.
func (*TxStream) AppendBatch ¶
func (s *TxStream) AppendBatch(ctx context.Context, batch []*protoblocktx.Tx)
AppendBatch appends a batch to the stream.
func (*TxStream) MakeGenerator ¶
func (s *TxStream) MakeGenerator() *RateLimiterGenerator[*protoblocktx.Tx]
MakeGenerator creates a new generator that consumes from the stream. Each generator must be used from a single goroutine, but different generators from the same Stream can be used concurrently.
type UUIDGenerator ¶
UUIDGenerator generates UUIDs.
type UniformDist ¶
type UniformDist struct {
Min float64 `mapstructure:"min" yaml:"min,omitempty"`
Max float64 `mapstructure:"max" yaml:"max,omitempty"`
}
UniformDist describes uniform.
type UniformGenerator ¶
UniformGenerator generates values with a uniform distribution.
func (*UniformGenerator) Next ¶
func (d *UniformGenerator) Next() float64
Next yields the next uniform value.