github.com/neatio-net/neatio@v1.7.3-0.20231114194659-f4d7a2226baa/utilities/metrics/ewma.go (about) 1 package metrics 2 3 import ( 4 "math" 5 "sync" 6 "sync/atomic" 7 ) 8 9 type EWMA interface { 10 Rate() float64 11 Snapshot() EWMA 12 Tick() 13 Update(int64) 14 } 15 16 func NewEWMA(alpha float64) EWMA { 17 if !Enabled { 18 return NilEWMA{} 19 } 20 return &StandardEWMA{alpha: alpha} 21 } 22 23 func NewEWMA1() EWMA { 24 return NewEWMA(1 - math.Exp(-5.0/60.0/1)) 25 } 26 27 func NewEWMA5() EWMA { 28 return NewEWMA(1 - math.Exp(-5.0/60.0/5)) 29 } 30 31 func NewEWMA15() EWMA { 32 return NewEWMA(1 - math.Exp(-5.0/60.0/15)) 33 } 34 35 type EWMASnapshot float64 36 37 func (a EWMASnapshot) Rate() float64 { return float64(a) } 38 39 func (a EWMASnapshot) Snapshot() EWMA { return a } 40 41 func (EWMASnapshot) Tick() { 42 panic("Tick called on an EWMASnapshot") 43 } 44 45 func (EWMASnapshot) Update(int64) { 46 panic("Update called on an EWMASnapshot") 47 } 48 49 type NilEWMA struct{} 50 51 func (NilEWMA) Rate() float64 { return 0.0 } 52 53 func (NilEWMA) Snapshot() EWMA { return NilEWMA{} } 54 55 func (NilEWMA) Tick() {} 56 57 func (NilEWMA) Update(n int64) {} 58 59 type StandardEWMA struct { 60 uncounted int64 61 alpha float64 62 rate float64 63 init bool 64 mutex sync.Mutex 65 } 66 67 func (a *StandardEWMA) Rate() float64 { 68 a.mutex.Lock() 69 defer a.mutex.Unlock() 70 return a.rate * float64(1e9) 71 } 72 73 func (a *StandardEWMA) Snapshot() EWMA { 74 return EWMASnapshot(a.Rate()) 75 } 76 77 func (a *StandardEWMA) Tick() { 78 count := atomic.LoadInt64(&a.uncounted) 79 atomic.AddInt64(&a.uncounted, -count) 80 instantRate := float64(count) / float64(5e9) 81 a.mutex.Lock() 82 defer a.mutex.Unlock() 83 if a.init { 84 a.rate += a.alpha * (instantRate - a.rate) 85 } else { 86 a.init = true 87 a.rate = instantRate 88 } 89 } 90 91 func (a *StandardEWMA) Update(n int64) { 92 atomic.AddInt64(&a.uncounted, n) 93 }