Skip to content

Commit ac6abfb

Browse files
author
livingentity
authored
LBStrategy-aware estimator (#2043)
* fix estimator * LBStrategy-aware estimator * typo * cosmetics
1 parent a20d168 commit ac6abfb

1 file changed

Lines changed: 36 additions & 14 deletions

File tree

dnscrypt-proxy/serversInfo.go

Lines changed: 36 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import (
2424
)
2525

2626
const (
27-
RTTEwmaDecay = 10.0
27+
RTTEwmaDecay = 15.0
2828
)
2929

3030
type RegisteredServer struct {
@@ -67,6 +67,7 @@ type ServerInfo struct {
6767

6868
type LBStrategy interface {
6969
getCandidate(serversCount int) int
70+
getActiveCount(serversCount int) int
7071
}
7172

7273
type LBStrategyP2 struct{}
@@ -75,30 +76,50 @@ func (LBStrategyP2) getCandidate(serversCount int) int {
7576
return rand.Intn(Min(serversCount, 2))
7677
}
7778

79+
func (LBStrategyP2) getActiveCount(serversCount int) int {
80+
return Min(serversCount, 2)
81+
}
82+
7883
type LBStrategyPN struct{ n int }
7984

8085
func (s LBStrategyPN) getCandidate(serversCount int) int {
8186
return rand.Intn(Min(serversCount, s.n))
8287
}
8388

89+
func (s LBStrategyPN) getActiveCount(serversCount int) int {
90+
return Min(serversCount, s.n)
91+
}
92+
8493
type LBStrategyPH struct{}
8594

8695
func (LBStrategyPH) getCandidate(serversCount int) int {
8796
return rand.Intn(Max(Min(serversCount, 2), serversCount/2))
8897
}
8998

99+
func (LBStrategyPH) getActiveCount(serversCount int) int {
100+
return Max(Min(serversCount, 2), serversCount/2)
101+
}
102+
90103
type LBStrategyFirst struct{}
91104

92105
func (LBStrategyFirst) getCandidate(int) int {
93106
return 0
94107
}
95108

109+
func (LBStrategyFirst) getActiveCount(int) int {
110+
return 1
111+
}
112+
96113
type LBStrategyRandom struct{}
97114

98115
func (LBStrategyRandom) getCandidate(serversCount int) int {
99116
return rand.Intn(serversCount)
100117
}
101118

119+
func (LBStrategyRandom) getActiveCount(serversCount int) int {
120+
return serversCount
121+
}
122+
102123
var DefaultLBStrategy = LBStrategyP2{}
103124

104125
type DNSCryptRelay struct {
@@ -227,29 +248,30 @@ func (serversInfo *ServersInfo) refresh(proxy *Proxy) (int, error) {
227248

228249
func (serversInfo *ServersInfo) estimatorUpdate() {
229250
// serversInfo.RWMutex is assumed to be Locked
230-
candidate := rand.Intn(len(serversInfo.inner))
231-
if candidate == 0 {
251+
serversCount := len(serversInfo.inner)
252+
activeCount := serversInfo.lbStrategy.getActiveCount(serversCount)
253+
if activeCount == serversCount {
232254
return
233255
}
234-
candidateRtt, currentBestRtt := serversInfo.inner[candidate].rtt.Value(), serversInfo.inner[0].rtt.Value()
235-
if currentBestRtt < 0 {
236-
currentBestRtt = candidateRtt
237-
serversInfo.inner[0].rtt.Set(currentBestRtt)
256+
candidate, currentActive := rand.Intn(serversCount-activeCount)+activeCount, rand.Intn(activeCount)
257+
candidateRtt, currentActiveRtt := serversInfo.inner[candidate].rtt.Value(), serversInfo.inner[currentActive].rtt.Value()
258+
if currentActiveRtt < 0 {
259+
currentActiveRtt = candidateRtt
260+
serversInfo.inner[currentActive].rtt.Set(currentActiveRtt)
238261
}
239262
partialSort := false
240-
if candidateRtt < currentBestRtt {
241-
serversInfo.inner[candidate], serversInfo.inner[0] = serversInfo.inner[0], serversInfo.inner[candidate]
263+
if candidateRtt < currentActiveRtt {
264+
serversInfo.inner[candidate], serversInfo.inner[currentActive] = serversInfo.inner[currentActive], serversInfo.inner[candidate]
265+
dlog.Debugf("New preferred candidate: %s (RTT: %d vs previous: %d)", serversInfo.inner[currentActive].Name, int(candidateRtt), int(currentActiveRtt))
242266
partialSort = true
243-
dlog.Debugf("New preferred candidate: %v (rtt: %d vs previous: %d)", serversInfo.inner[0].Name, int(candidateRtt), int(currentBestRtt))
244-
} else if candidateRtt > 0 && candidateRtt >= currentBestRtt*4.0 {
267+
} else if candidateRtt > 0 && candidateRtt > serversInfo.inner[activeCount].rtt.Value() {
245268
if time.Since(serversInfo.inner[candidate].lastActionTS) > time.Duration(1*time.Minute) {
246-
serversInfo.inner[candidate].rtt.Add(MinF(MaxF(candidateRtt/2.0, currentBestRtt*2.0), candidateRtt))
247-
dlog.Debugf("Giving a new chance to candidate [%s], lowering its RTT from %d to %d (best: %d)", serversInfo.inner[candidate].Name, int(candidateRtt), int(serversInfo.inner[candidate].rtt.Value()), int(currentBestRtt))
269+
serversInfo.inner[candidate].rtt.Add(serversInfo.inner[activeCount].rtt.Value())
270+
dlog.Debugf("Giving a new chance to candidate [%s], lowering its RTT from %d to %d (best: %d)", serversInfo.inner[candidate].Name, int(candidateRtt), int(serversInfo.inner[candidate].rtt.Value()), int(serversInfo.inner[0].rtt.Value()))
248271
partialSort = true
249272
}
250273
}
251274
if partialSort {
252-
serversCount := len(serversInfo.inner)
253275
for i := 1; i < serversCount; i++ {
254276
if serversInfo.inner[i-1].rtt.Value() > serversInfo.inner[i].rtt.Value() {
255277
serversInfo.inner[i-1], serversInfo.inner[i] = serversInfo.inner[i], serversInfo.inner[i-1]

0 commit comments

Comments
 (0)