-
Notifications
You must be signed in to change notification settings - Fork 11
/
path_statistics.go
64 lines (53 loc) · 1.17 KB
/
path_statistics.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
package router
import (
"sync"
"time"
)
const (
inertiaFactor = 5
)
type PathStatistics struct {
locker sync.RWMutex
count uint64
timedOut float64
latency time.Duration
}
func (stats *PathStatistics) LockDo(fn func()) {
stats.locker.Lock()
defer stats.locker.Unlock()
fn()
}
func (stats *PathStatistics) RLockDo(fn func()) {
stats.locker.RLock()
defer stats.locker.RUnlock()
fn()
}
func (stats *PathStatistics) Consider(latency time.Duration, isLoss bool) {
stats.LockDo(func() {
inertiaFactorCur := uint64(inertiaFactor)
if stats.count < inertiaFactor {
inertiaFactorCur = stats.count
}
stats.count++
timedOut := float64(0)
if isLoss {
timedOut = 1
}
stats.timedOut = (stats.timedOut*float64(inertiaFactorCur) + timedOut) / (float64(inertiaFactorCur) + 1)
if !isLoss {
stats.latency = time.Duration((uint64(stats.latency)*inertiaFactorCur + uint64(latency)) / (inertiaFactorCur + 1))
}
})
}
func (stats *PathStatistics) Latency() (result time.Duration) {
stats.RLockDo(func() {
result = stats.latency
})
return
}
func (stats *PathStatistics) TimedOut() (result float64) {
stats.RLockDo(func() {
result = stats.timedOut
})
return
}