code optimize

This commit is contained in:
jebbs 2022-10-11 14:50:51 +08:00
parent fe4fa2ab0c
commit 04ceb67921
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
type Balancer interface {
Select() *Node
Pick() *Node
}
type rttBasedBalancer struct {
@ -49,7 +49,7 @@ func newRTTBasedBalancer(
}
// Select selects qualified nodes
func (s *rttBasedBalancer) Select() *Node {
func (s *rttBasedBalancer) Pick() *Node {
nodes := s.HealthCheck.NodesByCategory()
var candidates []*Node
if len(nodes.Qualified) > 0 {
@ -62,7 +62,7 @@ func (s *rttBasedBalancer) Select() *Node {
candidates = nodes.Untested
shuffleNodes(candidates)
}
selects := pickNodes(
selects := selectNodes(
candidates, s.logger,
int(s.options.Pick.Expected), s.options.Pick.Baselines,
)
@ -73,62 +73,6 @@ func (s *rttBasedBalancer) Select() *Node {
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) {
sort.Slice(nodes, func(i, j int) bool {
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 {
if s.Balancer != nil {
selected := s.Balancer.Select()
selected := s.Balancer.Pick()
if selected == nil {
return s.fallback
}