code optimize

This commit is contained in:
jebbs 2022-10-11 14:50:51 +08:00
parent 3d44156b67
commit 5c2c76b85c
3 changed files with 70 additions and 60 deletions

View File

@ -14,7 +14,7 @@ var _ Balancer = (*rttBasedBalancer)(nil)
// Balancer is interface for load balancers // Balancer is interface for load balancers
type Balancer interface { type Balancer interface {
Select() *Node Pick() *Node
} }
type rttBasedBalancer struct { type rttBasedBalancer struct {
@ -49,7 +49,7 @@ func newRTTBasedBalancer(
} }
// Select selects qualified nodes // Select selects qualified nodes
func (s *rttBasedBalancer) Select() *Node { func (s *rttBasedBalancer) Pick() *Node {
nodes := s.HealthCheck.NodesByCategory() nodes := s.HealthCheck.NodesByCategory()
var candidates []*Node var candidates []*Node
if len(nodes.Qualified) > 0 { if len(nodes.Qualified) > 0 {
@ -62,7 +62,7 @@ func (s *rttBasedBalancer) Select() *Node {
candidates = nodes.Untested candidates = nodes.Untested
shuffleNodes(candidates) shuffleNodes(candidates)
} }
selects := pickNodes( selects := selectNodes(
candidates, s.logger, candidates, s.logger,
int(s.options.Pick.Expected), s.options.Pick.Baselines, int(s.options.Pick.Expected), s.options.Pick.Baselines,
) )
@ -73,62 +73,6 @@ func (s *rttBasedBalancer) Select() *Node {
return selects[rand.Intn(count)] return selects[rand.Intn(count)]
} }
// pickNodes selects nodes according to Baselines and Expected Count.
//
// The strategy always improves network response speed, not matter which mode below is configurated.
// But they can still have different priorities.
//
// 1. Bandwidth priority: no Baseline + Expected Count > 0.: selects `Expected Count` of nodes.
// (one if Expected Count <= 0)
//
// 2. Bandwidth priority advanced: Baselines + Expected Count > 0.
// Select `Expected Count` amount of nodes, and also those near them according to baselines.
// In other words, it selects according to different Baselines, until one of them matches
// the Expected Count, if no Baseline matches, Expected Count applied.
//
// 3. Speed priority: Baselines + `Expected Count <= 0`.
// go through all baselines until find selects, if not, select none. Used in combination
// with 'balancer.fallbackTag', it means: selects qualified nodes or use the fallback.
func pickNodes(nodes []*Node, logger log.Logger, expected int, baselines []option.Duration) []*Node {
if len(nodes) == 0 {
// s.logger.Debug("no qualified nodes")
return nil
}
expected2 := int(expected)
availableCount := len(nodes)
if expected2 > availableCount {
return nodes
}
if expected2 <= 0 {
expected2 = 1
}
if len(baselines) == 0 {
return nodes[:expected2]
}
count := 0
// go through all base line until find expected selects
for _, b := range baselines {
baseline := time.Duration(b)
for i := 0; i < availableCount; i++ {
if nodes[i].Weighted > baseline {
break
}
count = i + 1
}
// don't continue if find expected selects
if count >= expected2 {
logger.Debug("applied baseline: ", baseline)
break
}
}
if expected > 0 && count < expected2 {
count = expected2
}
return nodes[:count]
}
func sortNodes(nodes []*Node) { func sortNodes(nodes []*Node) {
sort.Slice(nodes, func(i, j int) bool { sort.Slice(nodes, func(i, j int) bool {
left := nodes[i] left := nodes[i]

View File

@ -0,0 +1,66 @@
package balancer
import (
"time"
"github.com/sagernet/sing-box/log"
"github.com/sagernet/sing-box/option"
)
// selectNodes selects nodes according to Baselines and Expected Count.
//
// The strategy always improves network response speed, not matter which mode below is configurated.
// But they can still have different priorities.
//
// 1. Bandwidth priority: no Baseline + Expected Count > 0.: selects `Expected Count` of nodes.
// (one if Expected Count <= 0)
//
// 2. Bandwidth priority advanced: Baselines + Expected Count > 0.
// Select `Expected Count` amount of nodes, and also those near them according to baselines.
// In other words, it selects according to different Baselines, until one of them matches
// the Expected Count, if no Baseline matches, Expected Count applied.
//
// 3. Speed priority: Baselines + `Expected Count <= 0`.
// go through all baselines until find selects, if not, select none. Used in combination
// with 'balancer.fallbackTag', it means: selects qualified nodes or use the fallback.
func selectNodes(nodes []*Node, logger log.Logger, expected int, baselines []option.Duration) []*Node {
if len(nodes) == 0 {
// s.logger.Debug("no qualified nodes")
return nil
}
expected2 := int(expected)
availableCount := len(nodes)
if expected2 > availableCount {
return nodes
}
if expected2 <= 0 {
expected2 = 1
}
if len(baselines) == 0 {
return nodes[:expected2]
}
count := 0
// go through all base line until find expected selects
for _, b := range baselines {
baseline := time.Duration(b)
for i := 0; i < availableCount; i++ {
if nodes[i].Weighted > baseline {
break
}
count = i + 1
}
// don't continue if find expected selects
if count >= expected2 {
if logger != nil {
logger.Debug("applied baseline: ", baseline)
}
break
}
}
if expected > 0 && count < expected2 {
count = expected2
}
return nodes[:count]
}

View File

@ -129,7 +129,7 @@ func (s *Balancer) setBalancer(b balancer.Balancer) error {
func (s *Balancer) pick() adapter.Outbound { func (s *Balancer) pick() adapter.Outbound {
if s.Balancer != nil { if s.Balancer != nil {
selected := s.Balancer.Select() selected := s.Balancer.Pick()
if selected == nil { if selected == nil {
return s.fallback return s.fallback
} }