Replace our EWMA with VividCortex/ewma
https://github.com/VividCortex/ewma looks simpler than ours.
https://github.com/VividCortex/ewma
@rcrowley @mihasya The package calculates an EWMA that is time-independent, meaning that old data points decay with each incoming metric (instead of decaying over time). If this approach were to be used, then calling NewEMWA1(), NewEMWA15(), etc. would not accurately reflect a time-sensitive EWMA.
An alternative solution is to add a timestamp field to StandardEWMA. This way, the EWMA can be calculated on demand (i.e any time Rate() is called), as opposed to concurrently, using the following formula:
[ (1 - alpha) ^ periods ] * oldRate
Where periods are the number of seconds (or any other time interval) that have passed since the last update. Here is an example in Go:
func (a *StandardEWMA) Rate() float64 {
if atomic.LoadUint32(&a.init) == 0 {
return 0
}
// Calculate periods since last update.
lastTime := atomic.LoadInt64(&a.time)
currentTime := time.Now().UTC().UnixNano()
// 5-second periods. This is equivalent to Tick()-ing every 5 seconds.
periods := math.Floor(float64(currentTime-lastTime) / float64(5e9))
// Calculate new rate based on time since last update.
// [(1-alpha)^periods] * lastRate
lastRate := math.Float64frombits(atomic.LoadUint64(&a.rate))
currentRate := math.Pow(1-a.alpha, periods) * lastRate
return currentRate * 1e9
}
Where a.time is the Unix timestamp of when the StandardEMWA was updated last.
This would also fix Issue #283
Let me know if you agree with my approach and whether you'd like for me to open a PR.