mirror of
https://github.com/daeuniverse/dae.git
synced 2025-07-06 08:22:38 +07:00
optimize: latencyString shows realLatency(+offset) (#307)
This commit is contained in:
@ -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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user