2016-06-01 02:31:50 +08:00
|
|
|
package peerstore
|
2015-10-01 06:42:55 +08:00
|
|
|
|
|
|
|
import (
|
|
|
|
"sync"
|
|
|
|
"time"
|
2016-06-01 02:31:50 +08:00
|
|
|
|
2019-05-31 21:51:16 +08:00
|
|
|
"github.com/libp2p/go-libp2p-core/peer"
|
2015-10-01 06:42:55 +08:00
|
|
|
)
|
|
|
|
|
|
|
|
// LatencyEWMASmooting governs the decay of the EWMA (the speed
|
|
|
|
// at which it changes). This must be a normalized (0-1) value.
|
|
|
|
// 1 is 100% change, 0 is no change.
|
|
|
|
var LatencyEWMASmoothing = 0.1
|
|
|
|
|
|
|
|
type metrics struct {
|
2016-06-01 02:31:50 +08:00
|
|
|
latmap map[peer.ID]time.Duration
|
2015-10-01 06:42:55 +08:00
|
|
|
latmu sync.RWMutex
|
|
|
|
}
|
|
|
|
|
2016-10-05 09:01:51 +08:00
|
|
|
func NewMetrics() *metrics {
|
2015-10-01 06:42:55 +08:00
|
|
|
return &metrics{
|
2016-06-01 02:31:50 +08:00
|
|
|
latmap: make(map[peer.ID]time.Duration),
|
2015-10-01 06:42:55 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// RecordLatency records a new latency measurement
|
2016-06-01 02:31:50 +08:00
|
|
|
func (m *metrics) RecordLatency(p peer.ID, next time.Duration) {
|
2015-10-01 06:42:55 +08:00
|
|
|
nextf := float64(next)
|
|
|
|
s := LatencyEWMASmoothing
|
|
|
|
if s > 1 || s < 0 {
|
|
|
|
s = 0.1 // ignore the knob. it's broken. look, it jiggles.
|
|
|
|
}
|
|
|
|
|
|
|
|
m.latmu.Lock()
|
|
|
|
ewma, found := m.latmap[p]
|
|
|
|
ewmaf := float64(ewma)
|
|
|
|
if !found {
|
|
|
|
m.latmap[p] = next // when no data, just take it as the mean.
|
|
|
|
} else {
|
|
|
|
nextf = ((1.0 - s) * ewmaf) + (s * nextf)
|
|
|
|
m.latmap[p] = time.Duration(nextf)
|
|
|
|
}
|
|
|
|
m.latmu.Unlock()
|
|
|
|
}
|
|
|
|
|
|
|
|
// LatencyEWMA returns an exponentially-weighted moving avg.
|
|
|
|
// of all measurements of a peer's latency.
|
2016-06-01 02:31:50 +08:00
|
|
|
func (m *metrics) LatencyEWMA(p peer.ID) time.Duration {
|
2015-10-01 06:42:55 +08:00
|
|
|
m.latmu.RLock()
|
|
|
|
lat := m.latmap[p]
|
|
|
|
m.latmu.RUnlock()
|
|
|
|
return time.Duration(lat)
|
|
|
|
}
|