optimize: latencyString shows realLatency(+offset) (#307)

This commit is contained in:
Luo Chen
2023-09-02 23:59:03 +08:00
committed by GitHub
parent b9b1624b0b
commit eaf9684ec1
2 changed files with 50 additions and 57 deletions

View File

@ -23,7 +23,7 @@ const (
) )
type minLatency struct { type minLatency struct {
latency time.Duration sortingLatency time.Duration
dialer *Dialer dialer *Dialer
} }
@ -80,7 +80,7 @@ func NewAliveDialerSet(
selectionPolicy: selectionPolicy, selectionPolicy: selectionPolicy,
minLatency: minLatency{ minLatency: minLatency{
// Initiate the latency with a very big value. // Initiate the latency with a very big value.
latency: time.Hour, sortingLatency: time.Hour,
}, },
} }
for _, d := range dialers { for _, d := range dialers {
@ -102,9 +102,13 @@ func (a *AliveDialerSet) GetRand() *Dialer {
return a.inorderedAliveDialerSet[ind] return a.inorderedAliveDialerSet[ind]
} }
func (a *AliveDialerSet) SortingLatency(d *Dialer) time.Duration {
return a.dialerToLatency[d] + a.dialerToLatencyOffset[d]
}
// GetMinLatency acquires correct selectionPolicy. // GetMinLatency acquires correct selectionPolicy.
func (a *AliveDialerSet) GetMinLatency() (d *Dialer, latency time.Duration) { func (a *AliveDialerSet) GetMinLatency() (d *Dialer, latency time.Duration) {
return a.minLatency.dialer, a.minLatency.latency return a.minLatency.dialer, a.minLatency.sortingLatency
} }
func (a *AliveDialerSet) printLatencies() { func (a *AliveDialerSet) printLatencies() {
@ -113,55 +117,36 @@ func (a *AliveDialerSet) printLatencies() {
var alive []*struct { var alive []*struct {
d *Dialer d *Dialer
l time.Duration l time.Duration
o time.Duration
} }
for _, d := range a.inorderedAliveDialerSet { for _, d := range a.inorderedAliveDialerSet {
latency, ok := a.dialerToLatency[d] latency, ok := a.dialerToLatency[d]
if !ok { if !ok {
continue continue
} }
offset := a.dialerToLatencyOffset[d]
alive = append(alive, &struct { alive = append(alive, &struct {
d *Dialer d *Dialer
l time.Duration l time.Duration
}{d, latency}) o time.Duration
}{d, latency, offset})
} }
sort.SliceStable(alive, func(i, j int) bool { sort.SliceStable(alive, func(i, j int) bool {
return alive[i].l < alive[j].l return alive[i].l+alive[i].o < alive[j].l+alive[j].o
}) })
for i, dl := range alive { for i, dl := range alive {
builder.WriteString(fmt.Sprintf("%4d. %v: %v\n", i+1, dl.d.property.Name, a.latencyString(dl.d, dl.l))) builder.WriteString(fmt.Sprintf("%4d. %v: %v\n", i+1, dl.d.property.Name, latencyString(dl.l, dl.o)))
} }
a.log.Infoln(strings.TrimSuffix(builder.String(), "\n")) a.log.Infoln(strings.TrimSuffix(builder.String(), "\n"))
} }
func (a *AliveDialerSet) offsetLatency(d *Dialer, latency time.Duration, reverse bool) time.Duration {
offset := a.dialerToLatencyOffset[d]
var result time.Duration
if !reverse {
result = latency + offset
} else {
result = latency - offset
}
epsilon := 1 * time.Nanosecond
if result < +epsilon {
return +epsilon
}
if result > Timeout-epsilon {
result = Timeout - epsilon
}
return result
}
func (a *AliveDialerSet) latencyString(d *Dialer, afterLatency time.Duration) string {
return latencyString(afterLatency, a.offsetLatency(d, afterLatency, true))
}
// NotifyLatencyChange should be invoked when dialer every time latency and alive state changes. // NotifyLatencyChange should be invoked when dialer every time latency and alive state changes.
func (a *AliveDialerSet) NotifyLatencyChange(dialer *Dialer, alive bool) { func (a *AliveDialerSet) NotifyLatencyChange(dialer *Dialer, alive bool) {
a.mu.Lock() a.mu.Lock()
defer a.mu.Unlock() defer a.mu.Unlock()
var ( var (
rawLatency time.Duration rawLatency time.Duration
latency time.Duration sortingLatency time.Duration
hasLatency bool hasLatency bool
minPolicy bool minPolicy bool
) )
@ -178,11 +163,6 @@ func (a *AliveDialerSet) NotifyLatencyChange(dialer *Dialer, alive bool) {
hasLatency = rawLatency > 0 hasLatency = rawLatency > 0
minPolicy = true minPolicy = true
} }
if hasLatency {
latency = a.offsetLatency(dialer, rawLatency, false)
} else {
latency = rawLatency
}
if alive { if alive {
index := a.dialerToIndex[dialer] index := a.dialerToIndex[dialer]
@ -233,15 +213,16 @@ func (a *AliveDialerSet) NotifyLatencyChange(dialer *Dialer, alive bool) {
if hasLatency { if hasLatency {
bakOldBestDialer := a.minLatency.dialer bakOldBestDialer := a.minLatency.dialer
// Calc minLatency. // Calc minLatency.
a.dialerToLatency[dialer] = latency a.dialerToLatency[dialer] = rawLatency
sortingLatency = a.SortingLatency(dialer)
if alive && if alive &&
latency <= a.minLatency.latency && // To avoid arithmetic overflow. sortingLatency <= a.minLatency.sortingLatency && // To avoid arithmetic overflow.
latency <= a.minLatency.latency-a.tolerance { sortingLatency <= a.minLatency.sortingLatency-a.tolerance {
a.minLatency.latency = latency a.minLatency.sortingLatency = sortingLatency
a.minLatency.dialer = dialer a.minLatency.dialer = dialer
} else if a.minLatency.dialer == dialer { } else if a.minLatency.dialer == dialer {
a.minLatency.latency = latency a.minLatency.sortingLatency = sortingLatency
if !alive || latency > a.minLatency.latency { if !alive || sortingLatency > a.minLatency.sortingLatency {
// Latency increases. // Latency increases.
if !alive { if !alive {
a.minLatency.dialer = nil a.minLatency.dialer = nil
@ -265,7 +246,7 @@ func (a *AliveDialerSet) NotifyLatencyChange(dialer *Dialer, alive bool) {
oldDialerName = bakOldBestDialer.property.Name oldDialerName = bakOldBestDialer.property.Name
} }
a.log.WithFields(logrus.Fields{ a.log.WithFields(logrus.Fields{
string(a.selectionPolicy): a.latencyString(a.minLatency.dialer, a.minLatency.latency), string(a.selectionPolicy): latencyString(a.dialerToLatency[a.minLatency.dialer], a.dialerToLatencyOffset[a.minLatency.dialer]),
"_new_dialer": a.minLatency.dialer.property.Name, "_new_dialer": a.minLatency.dialer.property.Name,
"_old_dialer": oldDialerName, "_old_dialer": oldDialerName,
"group": a.dialerGroupName, "group": a.dialerGroupName,
@ -299,22 +280,23 @@ func (a *AliveDialerSet) calcMinLatency() {
var minLatency = time.Hour var minLatency = time.Hour
var minDialer *Dialer var minDialer *Dialer
for _, d := range a.inorderedAliveDialerSet { for _, d := range a.inorderedAliveDialerSet {
latency, ok := a.dialerToLatency[d] _, ok := a.dialerToLatency[d]
if !ok { if !ok {
continue continue
} }
if latency < minLatency { sortingLatency := a.SortingLatency(d)
minLatency = latency if sortingLatency < minLatency {
minLatency = sortingLatency
minDialer = d minDialer = d
} }
} }
if a.minLatency.dialer == nil { if a.minLatency.dialer == nil {
a.minLatency.latency = minLatency a.minLatency.sortingLatency = minLatency
a.minLatency.dialer = minDialer a.minLatency.dialer = minDialer
} else if minDialer != nil && } else if minDialer != nil &&
minLatency <= a.minLatency.latency && // To avoid arithmetic overflow. minLatency <= a.minLatency.sortingLatency && // To avoid arithmetic overflow.
minLatency <= a.minLatency.latency-a.tolerance { minLatency <= a.minLatency.sortingLatency-a.tolerance {
a.minLatency.latency = minLatency a.minLatency.sortingLatency = minLatency
a.minLatency.dialer = minDialer a.minLatency.dialer = minDialer
} }
} }

View File

@ -2,9 +2,20 @@ package dialer
import "time" import "time"
func latencyString(latencyAfterOffset, latencyBeforeOffset time.Duration) string { func showDuration(d time.Duration) string {
if latencyBeforeOffset == latencyAfterOffset { return d.Truncate(time.Millisecond).String()
return latencyAfterOffset.Truncate(time.Millisecond).String() }
}
return latencyAfterOffset.Truncate(time.Millisecond).String() + "(" + latencyBeforeOffset.Truncate(time.Millisecond).String() + ")" func latencyString(realLatency, latencyOffset time.Duration) string {
var offsetSign string = "+"
if latencyOffset < 0 {
offsetSign = "-"
}
var offsetPart string = ""
if latencyOffset != 0 {
offsetPart = "(" + offsetSign + showDuration(latencyOffset.Abs()) + "=" + showDuration(realLatency+latencyOffset) + ")"
}
return showDuration(realLatency) + offsetPart
} }