mirror of
https://github.com/SagerNet/sing-box.git
synced 2025-06-13 21:54:13 +08:00
code optimize
This commit is contained in:
parent
3d44156b67
commit
5c2c76b85c
@ -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]
|
||||
|
66
balancer/balancer_select.go
Normal file
66
balancer/balancer_select.go
Normal 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]
|
||||
}
|
@ -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
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user