qf

package
v0.7.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 6, 2022 License: MIT Imports: 8 Imported by: 0

README

Benchmarks for quorum functions with and without the request object

The question we want to answer in this document is: Will Gorums be faster if we generate quorum functions without the request parameter, when the request is not needed by the quorum function?

Below are three runs of the benchmark for three variants of using the quorum function.

  • The UseReqQF method actually receive and use the request object passed to the quorum function. If your quorum function needs the request object, you anyway have to use this approach.
  • The IgnoreReqQF method has the same function signature as UseReqQF, but ignores the request object by using a _ in the implementation. This would be the recommended approach if we make the quorum function signature always require the request object.
  • The WithoutReqQF method has a function signature without the request object, and as such it should be the fastest, since it does not need to pass the request object on the stack at all.

All three benchmark methods has the same number of allocations, and so we exclude those details from the results below.

The conclusion from the benchmarks below is that UseReqQF is always slower, which is to be expected. However, from three runs of the benchmark on the same machine (a mid-2013 MacPro), it is not possible to observe any relevant difference between WithoutReqQF and IgnoreReqQF. In conclusion, it does not appear to be any value keeping the qf_with_req option.

Running the benchmarks

First compile the qf proto file.

cd tests
make qf

To plot graphs based on the benchmarks, you will need benchgraph:

TODO(meling): fork this repo and fix the go.mod file

go get -v github.com/AntonioSun/benchgraph

To run the benchmarks:

cd qf
go test -bench=BenchmarkQF | benchgraph -title "Quorum Function Evaluation"
go test -bench=BenchmarkFullStackQF | benchgraph -title "Quorum Function Evaluation (full stack)"

To view plots for three separate runs with slice implementation and one with both map and slice implementations:

Documentation

Index

Constants

This section is empty.

Variables

View Source
var File_qf_qf_proto protoreflect.FileDescriptor

Functions

func RegisterQuorumFunctionServer

func RegisterQuorumFunctionServer(srv *gorums.Server, impl QuorumFunction)

Types

type Configuration

type Configuration struct {
	gorums.RawConfiguration
	// contains filtered or unexported fields
}

A Configuration represents a static set of nodes on which quorum remote procedure calls may be invoked.

func ConfigurationFromRaw added in v0.7.0

func ConfigurationFromRaw(rawCfg gorums.RawConfiguration, qspec QuorumSpec) *Configuration

ConfigurationFromRaw returns a new Configuration from the given raw configuration and QuorumSpec.

This function may for example be used to "clone" a configuration but install a different QuorumSpec:

cfg1, err := mgr.NewConfiguration(qspec1, opts...)
cfg2 := ConfigurationFromRaw(cfg1.RawConfig, qspec2)

func (Configuration) And added in v0.4.0

And returns a NodeListOption that can be used to create a new configuration combining c and d.

func (Configuration) Except added in v0.4.0

Except returns a NodeListOption that can be used to create a new configuration from c without the nodes in rm.

func (*Configuration) IgnoreReq

func (c *Configuration) IgnoreReq(ctx context.Context, in *Request) (resp *Response, err error)

IgnoreReq is a quorum call invoked on all nodes in configuration c, with the same argument in, and returns a combined result.

func (*Configuration) Nodes

func (c *Configuration) Nodes() []*Node

Nodes returns a slice of each available node. IDs are returned in the same order as they were provided in the creation of the Manager.

NOTE: mutating the returned slice is not supported.

func (*Configuration) UseReq

func (c *Configuration) UseReq(ctx context.Context, in *Request) (resp *Response, err error)

UseReq is a quorum call invoked on all nodes in configuration c, with the same argument in, and returns a combined result.

type Manager

type Manager struct {
	*gorums.RawManager
}

Manager maintains a connection pool of nodes on which quorum calls can be performed.

func NewManager

func NewManager(opts ...gorums.ManagerOption) (mgr *Manager)

NewManager returns a new Manager for managing connection to nodes added to the manager. This function accepts manager options used to configure various aspects of the manager.

func (*Manager) NewConfiguration

func (m *Manager) NewConfiguration(opts ...gorums.ConfigOption) (c *Configuration, err error)

NewConfiguration returns a configuration based on the provided list of nodes (required) and an optional quorum specification. The QuorumSpec is necessary for call types that must process replies. For configurations only used for unicast or multicast call types, a QuorumSpec is not needed. The QuorumSpec interface is also a ConfigOption. Nodes can be supplied using WithNodeMap or WithNodeList, or WithNodeIDs. A new configuration can also be created from an existing configuration, using the And, WithNewNodes, Except, and WithoutNodes methods.

func (*Manager) Nodes

func (m *Manager) Nodes() []*Node

Nodes returns a slice of available nodes on this manager. IDs are returned in the order they were added at creation of the manager.

type Node

type Node struct {
	*gorums.RawNode
}

Node encapsulates the state of a node on which a remote procedure call can be performed.

type QuorumFunction

type QuorumFunction interface {
	UseReq(ctx gorums.ServerCtx, request *Request) (response *Response, err error)
	IgnoreReq(ctx gorums.ServerCtx, request *Request) (response *Response, err error)
}

QuorumFunction is the server-side API for the QuorumFunction Service

type QuorumSpec

type QuorumSpec interface {
	gorums.ConfigOption

	// UseReqQF is the quorum function for the UseReq
	// quorum call method. The in parameter is the request object
	// supplied to the UseReq method at call time, and may or may not
	// be used by the quorum function. If the in parameter is not needed
	// you should implement your quorum function with '_ *Request'.
	UseReqQF(in *Request, replies map[uint32]*Response) (*Response, bool)

	// IgnoreReqQF is the quorum function for the IgnoreReq
	// quorum call method. The in parameter is the request object
	// supplied to the IgnoreReq method at call time, and may or may not
	// be used by the quorum function. If the in parameter is not needed
	// you should implement your quorum function with '_ *Request'.
	IgnoreReqQF(in *Request, replies map[uint32]*Response) (*Response, bool)
}

QuorumSpec is the interface of quorum functions for QuorumFunction.

type Request

type Request struct {
	Value int64 `protobuf:"varint,1,opt,name=Value,proto3" json:"Value,omitempty"`
	// contains filtered or unexported fields
}

func (*Request) Descriptor deprecated

func (*Request) Descriptor() ([]byte, []int)

Deprecated: Use Request.ProtoReflect.Descriptor instead.

func (*Request) GetValue

func (x *Request) GetValue() int64

func (*Request) ProtoMessage

func (*Request) ProtoMessage()

func (*Request) ProtoReflect

func (x *Request) ProtoReflect() protoreflect.Message

func (*Request) Reset

func (x *Request) Reset()

func (*Request) String

func (x *Request) String() string

type Response

type Response struct {
	Result int64 `protobuf:"varint,1,opt,name=Result,proto3" json:"Result,omitempty"`
	// contains filtered or unexported fields
}

func (*Response) Descriptor deprecated

func (*Response) Descriptor() ([]byte, []int)

Deprecated: Use Response.ProtoReflect.Descriptor instead.

func (*Response) GetResult

func (x *Response) GetResult() int64

func (*Response) ProtoMessage

func (*Response) ProtoMessage()

func (*Response) ProtoReflect

func (x *Response) ProtoReflect() protoreflect.Message

func (*Response) Reset

func (x *Response) Reset()

func (*Response) String

func (x *Response) String() string

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL