satellite/durability: make benchmark even quicker
To make sure that Benchmark tests are good, we run them with -short flag, eg: ``` go test -short -run=BenchmarkDurabilityProcess ``` Durability benchmark already supports this, but we can make it slightly more faster with using less sgements and pieces during the `-short` run. Change-Id: I9547ca1e3cd0178eb395a7a388f2e7936a9862d7
This commit is contained in:
parent
100519321e
commit
0ef3247d44
@ -10,6 +10,7 @@ import (
|
|||||||
|
|
||||||
"github.com/jtolio/eventkit"
|
"github.com/jtolio/eventkit"
|
||||||
"github.com/zeebo/errs"
|
"github.com/zeebo/errs"
|
||||||
|
"golang.org/x/exp/slices"
|
||||||
|
|
||||||
"storj.io/common/storj"
|
"storj.io/common/storj"
|
||||||
"storj.io/storj/satellite/metabase"
|
"storj.io/storj/satellite/metabase"
|
||||||
@ -73,6 +74,7 @@ type ReportConfig struct {
|
|||||||
// in this case this reporter will return 38 for the class "country:DE" (assuming all the other segments are more lucky).
|
// in this case this reporter will return 38 for the class "country:DE" (assuming all the other segments are more lucky).
|
||||||
type Report struct {
|
type Report struct {
|
||||||
healthStat map[string]*HealthStat
|
healthStat map[string]*HealthStat
|
||||||
|
busFactor HealthStat
|
||||||
classifiers []NodeClassifier
|
classifiers []NodeClassifier
|
||||||
aliasMap *metabase.NodeAliasMap
|
aliasMap *metabase.NodeAliasMap
|
||||||
nodes map[storj.NodeID]*nodeselection.SelectedNode
|
nodes map[storj.NodeID]*nodeselection.SelectedNode
|
||||||
@ -80,6 +82,7 @@ type Report struct {
|
|||||||
metabaseDB *metabase.DB
|
metabaseDB *metabase.DB
|
||||||
reporter func(n time.Time, name string, stat *HealthStat)
|
reporter func(n time.Time, name string, stat *HealthStat)
|
||||||
reportThreshold int
|
reportThreshold int
|
||||||
|
busFactorThreshold int
|
||||||
asOfSystemInterval time.Duration
|
asOfSystemInterval time.Duration
|
||||||
|
|
||||||
// map between classes (like "country:hu" and integer IDs)
|
// map between classes (like "country:hu" and integer IDs)
|
||||||
@ -88,19 +91,23 @@ type Report struct {
|
|||||||
|
|
||||||
// contains the available classes for each node alias.
|
// contains the available classes for each node alias.
|
||||||
classified [][]classID
|
classified [][]classID
|
||||||
|
|
||||||
|
maxPieceCount int
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewDurability creates the new instance.
|
// NewDurability creates the new instance.
|
||||||
func NewDurability(db overlay.DB, metabaseDB *metabase.DB, classifiers []NodeClassifier, reportThreshold int, asOfSystemInterval time.Duration) *Report {
|
func NewDurability(db overlay.DB, metabaseDB *metabase.DB, classifiers []NodeClassifier, maxPieceCount int, reportThreshold int, busFactorThreshold int, asOfSystemInterval time.Duration) *Report {
|
||||||
return &Report{
|
return &Report{
|
||||||
db: db,
|
db: db,
|
||||||
metabaseDB: metabaseDB,
|
metabaseDB: metabaseDB,
|
||||||
classifiers: classifiers,
|
classifiers: classifiers,
|
||||||
reportThreshold: reportThreshold,
|
reportThreshold: reportThreshold,
|
||||||
|
busFactorThreshold: busFactorThreshold,
|
||||||
asOfSystemInterval: asOfSystemInterval,
|
asOfSystemInterval: asOfSystemInterval,
|
||||||
nodes: make(map[storj.NodeID]*nodeselection.SelectedNode),
|
nodes: make(map[storj.NodeID]*nodeselection.SelectedNode),
|
||||||
healthStat: make(map[string]*HealthStat),
|
healthStat: make(map[string]*HealthStat),
|
||||||
reporter: reportToEventkit,
|
reporter: reportToEventkit,
|
||||||
|
maxPieceCount: maxPieceCount,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -159,6 +166,7 @@ func (c *Report) Fork(ctx context.Context) (rangedloop.Partial, error) {
|
|||||||
reportThreshold: c.reportThreshold,
|
reportThreshold: c.reportThreshold,
|
||||||
healthStat: make([]HealthStat, len(c.classID)),
|
healthStat: make([]HealthStat, len(c.classID)),
|
||||||
controlledByClassCache: make([]int32, len(c.classID)),
|
controlledByClassCache: make([]int32, len(c.classID)),
|
||||||
|
busFactorCache: make([]int32, 0, c.maxPieceCount),
|
||||||
classified: c.classified,
|
classified: c.classified,
|
||||||
}
|
}
|
||||||
return d, nil
|
return d, nil
|
||||||
@ -184,6 +192,7 @@ func (c *Report) Join(ctx context.Context, partial rangedloop.Partial) (err erro
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
c.busFactor.Update(fork.busFactor.Min(), fork.busFactor.Exemplar)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -209,12 +218,15 @@ type ObserverFork struct {
|
|||||||
controlledByClassCache []int32
|
controlledByClassCache []int32
|
||||||
|
|
||||||
healthStat []HealthStat
|
healthStat []HealthStat
|
||||||
|
busFactor HealthStat
|
||||||
classifiers []NodeClassifier
|
classifiers []NodeClassifier
|
||||||
aliasMap *metabase.NodeAliasMap
|
aliasMap *metabase.NodeAliasMap
|
||||||
nodes map[storj.NodeID]*nodeselection.SelectedNode
|
nodes map[storj.NodeID]*nodeselection.SelectedNode
|
||||||
classifierCache [][]string
|
classifierCache [][]string
|
||||||
|
busFactorCache []int32
|
||||||
|
|
||||||
reportThreshold int
|
reportThreshold int
|
||||||
|
busFactorThreshold int
|
||||||
|
|
||||||
classified [][]classID
|
classified [][]classID
|
||||||
}
|
}
|
||||||
@ -248,6 +260,8 @@ func (c *ObserverFork) Process(ctx context.Context, segments []rangedloop.Segmen
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
busFactorGroups := c.busFactorCache
|
||||||
|
|
||||||
streamLocation := fmt.Sprintf("%s/%d", s.StreamID, s.Position.Encode())
|
streamLocation := fmt.Sprintf("%s/%d", s.StreamID, s.Position.Encode())
|
||||||
for classID, count := range controlledByClass {
|
for classID, count := range controlledByClass {
|
||||||
if count == 0 {
|
if count == 0 {
|
||||||
@ -259,12 +273,30 @@ func (c *ObserverFork) Process(ctx context.Context, segments []rangedloop.Segmen
|
|||||||
|
|
||||||
diff := healthyPieceCount - int(count)
|
diff := healthyPieceCount - int(count)
|
||||||
|
|
||||||
|
busFactorGroups = append(busFactorGroups, count)
|
||||||
|
|
||||||
if c.reportThreshold > 0 && diff > c.reportThreshold {
|
if c.reportThreshold > 0 && diff > c.reportThreshold {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
c.healthStat[classID].Update(diff, streamLocation)
|
|
||||||
|
|
||||||
|
c.healthStat[classID].Update(diff, streamLocation)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
slices.SortFunc[int32](busFactorGroups, func(a int32, b int32) bool {
|
||||||
|
return a > b
|
||||||
|
})
|
||||||
|
rollingSum := 0
|
||||||
|
busFactor := 0
|
||||||
|
for _, count := range busFactorGroups {
|
||||||
|
if rollingSum < c.busFactorThreshold {
|
||||||
|
busFactor++
|
||||||
|
rollingSum += int(count)
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
c.busFactor.Update(busFactor, streamLocation)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -67,7 +67,7 @@ func TestDurability(t *testing.T) {
|
|||||||
c := NewDurability(nil, nil, []NodeClassifier{
|
c := NewDurability(nil, nil, []NodeClassifier{
|
||||||
func(node *nodeselection.SelectedNode) string {
|
func(node *nodeselection.SelectedNode) string {
|
||||||
return "net:" + node.LastNet
|
return "net:" + node.LastNet
|
||||||
}}, 0, 0)
|
}}, 110, 0, 0, 0)
|
||||||
|
|
||||||
c.aliasMap = metabase.NewNodeAliasMap(aliases)
|
c.aliasMap = metabase.NewNodeAliasMap(aliases)
|
||||||
for _, node := range storageNodes {
|
for _, node := range storageNodes {
|
||||||
@ -123,7 +123,7 @@ func TestDurabilityUnknownNode(t *testing.T) {
|
|||||||
c := NewDurability(nil, nil, []NodeClassifier{
|
c := NewDurability(nil, nil, []NodeClassifier{
|
||||||
func(node *nodeselection.SelectedNode) string {
|
func(node *nodeselection.SelectedNode) string {
|
||||||
return "net:" + node.LastNet
|
return "net:" + node.LastNet
|
||||||
}}, 0, 0)
|
}}, 110, 0, 0, 0)
|
||||||
|
|
||||||
c.aliasMap = metabase.NewNodeAliasMap(aliases)
|
c.aliasMap = metabase.NewNodeAliasMap(aliases)
|
||||||
for _, node := range storageNodes {
|
for _, node := range storageNodes {
|
||||||
@ -165,14 +165,61 @@ func TestDurabilityUnknownNode(t *testing.T) {
|
|||||||
require.Equal(t, 0, c.healthStat["net:127.0.0.1"].Min())
|
require.Equal(t, 0, c.healthStat["net:127.0.0.1"].Min())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestBusFactor(t *testing.T) {
|
||||||
|
ctx := testcontext.New(t)
|
||||||
|
f := ObserverFork{}
|
||||||
|
|
||||||
|
for i := 0; i < 100; i++ {
|
||||||
|
f.classified = append(f.classified, []classID{classID((i))})
|
||||||
|
}
|
||||||
|
f.controlledByClassCache = make([]int32, 100)
|
||||||
|
f.busFactorCache = make([]int32, 300)
|
||||||
|
f.healthStat = make([]HealthStat, 100)
|
||||||
|
f.busFactorThreshold = 26
|
||||||
|
|
||||||
|
createSegments := func(groups ...int) []rangedloop.Segment {
|
||||||
|
var pieces []metabase.AliasPiece
|
||||||
|
ix := uint16(0)
|
||||||
|
groupIndex := 0
|
||||||
|
for _, group := range groups {
|
||||||
|
for i := 0; i < group; i++ {
|
||||||
|
pieces = append(pieces, metabase.AliasPiece{
|
||||||
|
Number: ix,
|
||||||
|
Alias: metabase.NodeAlias(groupIndex),
|
||||||
|
})
|
||||||
|
ix++
|
||||||
|
}
|
||||||
|
groupIndex++
|
||||||
|
}
|
||||||
|
return []rangedloop.Segment{
|
||||||
|
{
|
||||||
|
StreamID: testrand.UUID(),
|
||||||
|
AliasPieces: pieces,
|
||||||
|
Redundancy: storj.RedundancyScheme{
|
||||||
|
ShareSize: 123,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
err := f.Process(ctx, createSegments(10, 10, 10, 10, 5, 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1))
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, 3, f.busFactor.Min())
|
||||||
|
}
|
||||||
|
|
||||||
func BenchmarkDurabilityProcess(b *testing.B) {
|
func BenchmarkDurabilityProcess(b *testing.B) {
|
||||||
ctx := context.TODO()
|
ctx := context.TODO()
|
||||||
|
|
||||||
rng := rand.New(rand.NewSource(0))
|
rng := rand.New(rand.NewSource(0))
|
||||||
|
|
||||||
nodeNo := 20000
|
nodeNo := 20000
|
||||||
|
// create 2500 segments (usual observer loop batch size) with 80 pieces
|
||||||
|
segmentNo := 2500
|
||||||
|
pieceNo := 80
|
||||||
if testing.Short() {
|
if testing.Short() {
|
||||||
nodeNo = 10
|
nodeNo = 10
|
||||||
|
segmentNo = 10
|
||||||
|
pieceNo = 10
|
||||||
}
|
}
|
||||||
|
|
||||||
nodeMap := make(map[storj.NodeID]*nodeselection.SelectedNode)
|
nodeMap := make(map[storj.NodeID]*nodeselection.SelectedNode)
|
||||||
@ -201,14 +248,14 @@ func BenchmarkDurabilityProcess(b *testing.B) {
|
|||||||
|
|
||||||
var segments []rangedloop.Segment
|
var segments []rangedloop.Segment
|
||||||
{
|
{
|
||||||
// create 2500 segments (usual observer loop batch size) with 80 pieces
|
|
||||||
for i := 0; i < 2500; i++ {
|
for i := 0; i < segmentNo; i++ {
|
||||||
var id uuid.UUID
|
var id uuid.UUID
|
||||||
rng.Read(id[:])
|
rng.Read(id[:])
|
||||||
|
|
||||||
var pieces metabase.Pieces
|
var pieces metabase.Pieces
|
||||||
var aliasPieces metabase.AliasPieces
|
var aliasPieces metabase.AliasPieces
|
||||||
for j := 0; j < 80; j++ {
|
for j := 0; j < pieceNo; j++ {
|
||||||
nodeIx := rand.Intn(len(aliasToNode) - 1)
|
nodeIx := rand.Intn(len(aliasToNode) - 1)
|
||||||
pieces = append(pieces, metabase.Piece{
|
pieces = append(pieces, metabase.Piece{
|
||||||
Number: uint16(j),
|
Number: uint16(j),
|
||||||
|
@ -160,7 +160,7 @@ func NewRangedLoop(log *zap.Logger, db DB, metabaseDB *metabase.DB, config *Conf
|
|||||||
func(node *nodeselection.SelectedNode) string {
|
func(node *nodeselection.SelectedNode) string {
|
||||||
return "c:" + node.CountryCode.String()
|
return "c:" + node.CountryCode.String()
|
||||||
},
|
},
|
||||||
}, config.Metainfo.RS.Repair, config.RangedLoop.AsOfSystemInterval)
|
}, config.Metainfo.RS.Total, config.Metainfo.RS.Repair, config.Metainfo.RS.Repair-config.Metainfo.RS.Min, config.RangedLoop.AsOfSystemInterval)
|
||||||
}
|
}
|
||||||
|
|
||||||
{ // setup overlay
|
{ // setup overlay
|
||||||
|
Loading…
Reference in New Issue
Block a user