frostfs-sdk-go/netmap/context.go
Leonard Lyubich 723ba5ee45 [#227] netmap: Do not use intermediate types for placement
Support preprocessing within the `NodeInfo` type. Provide methods for
placement directly from the `NodeInfo` type. Returns slice of slices of
`NodeInfo` from placement methods of `Netmap`. Remove no longer needed
`Node` and `Nodes` types.

```
name            old time/op    new time/op    delta
ManySelects-12    19.7µs ±14%    15.8µs ±15%  -19.70%  (p=0.000 n=20+20)

name            old alloc/op   new alloc/op   delta
ManySelects-12    8.65kB ± 0%    6.22kB ± 0%  -28.03%  (p=0.000 n=20+20)

name            old allocs/op  new allocs/op  delta
ManySelects-12      82.0 ± 0%      81.0 ± 0%   -1.22%  (p=0.000 n=20+20)
```

Signed-off-by: Leonard Lyubich <leonard@nspcc.ru>
2022-06-15 20:50:32 +03:00

94 lines
2.7 KiB
Go

package netmap
import (
"errors"
"github.com/nspcc-dev/hrw"
)
// context contains references to named filters and cached numeric values.
type context struct {
// Netmap is a netmap structure to operate on.
Netmap *Netmap
// Filters stores processed filters.
Filters map[string]*Filter
// Selectors stores processed selectors.
Selectors map[string]*Selector
// Selections stores result of selector processing.
Selections map[string][]nodes
// numCache stores parsed numeric values.
numCache map[string]uint64
// pivot is a seed for HRW.
pivot []byte
// pivotHash is a saved HRW hash of pivot
pivotHash uint64
// aggregator is returns aggregator determining bucket weight.
// By default it returns mean value from IQR interval.
aggregator func() aggregator
// weightFunc is a weighting function for determining node priority.
// By default in combines favours low price and high capacity.
weightFunc weightFunc
// container backup factor is a factor for selector counters that expand
// amount of chosen nodes.
cbf uint32
}
// Various validation errors.
var (
ErrMissingField = errors.New("netmap: nil field")
ErrInvalidFilterName = errors.New("netmap: filter name is invalid")
ErrInvalidNumber = errors.New("netmap: number value expected")
ErrInvalidFilterOp = errors.New("netmap: invalid filter operation")
ErrFilterNotFound = errors.New("netmap: filter not found")
ErrNonEmptyFilters = errors.New("netmap: simple filter must no contain sub-filters")
ErrNotEnoughNodes = errors.New("netmap: not enough nodes to SELECT from")
ErrSelectorNotFound = errors.New("netmap: selector not found")
ErrUnnamedTopFilter = errors.New("netmap: all filters on top level must be named")
)
// newContext creates new context. It contains various caches.
// In future it may create hierarchical netmap structure to work with.
func newContext(nm *Netmap) *context {
return &context{
Netmap: nm,
Filters: make(map[string]*Filter),
Selectors: make(map[string]*Selector),
Selections: make(map[string][]nodes),
numCache: make(map[string]uint64),
aggregator: newMeanIQRAgg,
weightFunc: GetDefaultWeightFunc(nm.nodes),
cbf: defaultCBF,
}
}
func (c *context) setPivot(pivot []byte) {
if len(pivot) != 0 {
c.pivot = pivot
c.pivotHash = hrw.Hash(pivot)
}
}
func (c *context) setCBF(cbf uint32) {
if cbf == 0 {
c.cbf = defaultCBF
} else {
c.cbf = cbf
}
}
// GetDefaultWeightFunc returns default weighting function.
func GetDefaultWeightFunc(ns nodes) weightFunc {
mean := newMeanAgg()
min := newMinAgg()
for i := range ns {
mean.Add(float64(ns[i].capacity()))
min.Add(float64(ns[i].price()))
}
return newWeightFunc(
newSigmoidNorm(mean.Compute()),
newReverseMinNorm(min.Compute()))
}