|
|
@ -2,17 +2,17 @@ package metrics |
|
|
|
|
|
|
|
|
|
|
|
import ( |
|
|
|
import ( |
|
|
|
"math" |
|
|
|
"math" |
|
|
|
|
|
|
|
"math/rand" |
|
|
|
|
|
|
|
"sync" |
|
|
|
"testing" |
|
|
|
"testing" |
|
|
|
|
|
|
|
"time" |
|
|
|
) |
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
const epsilon = 0.0000000000000001 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func BenchmarkEWMA(b *testing.B) { |
|
|
|
func BenchmarkEWMA(b *testing.B) { |
|
|
|
a := NewEWMA1() |
|
|
|
a := NewEWMA1() |
|
|
|
b.ResetTimer() |
|
|
|
b.ResetTimer() |
|
|
|
for i := 0; i < b.N; i++ { |
|
|
|
for i := 0; i < b.N; i++ { |
|
|
|
a.Update(1) |
|
|
|
a.Update(1) |
|
|
|
a.Tick() |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -23,67 +23,74 @@ func BenchmarkEWMAParallel(b *testing.B) { |
|
|
|
b.RunParallel(func(pb *testing.PB) { |
|
|
|
b.RunParallel(func(pb *testing.PB) { |
|
|
|
for pb.Next() { |
|
|
|
for pb.Next() { |
|
|
|
a.Update(1) |
|
|
|
a.Update(1) |
|
|
|
a.Tick() |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
}) |
|
|
|
}) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func TestEWMA1(t *testing.T) { |
|
|
|
// exercise race detector.
|
|
|
|
|
|
|
|
func TestEWMAConcurrency(t *testing.T) { |
|
|
|
a := NewEWMA1() |
|
|
|
a := NewEWMA1() |
|
|
|
a.Update(3) |
|
|
|
wg := &sync.WaitGroup{} |
|
|
|
a.Tick() |
|
|
|
for i := 0; i < 100; i++ { |
|
|
|
for i, want := range []float64{0.6, |
|
|
|
wg.Add(1) |
|
|
|
0.22072766470286553, 0.08120116994196772, 0.029872241020718428, |
|
|
|
go func(ewma EWMA, wg *sync.WaitGroup) { |
|
|
|
0.01098938333324054, 0.004042768199451294, 0.0014872513059998212, |
|
|
|
a.Update(rand.Int63()) |
|
|
|
0.0005471291793327122, 0.00020127757674150815, 7.404588245200814e-05, |
|
|
|
wg.Done() |
|
|
|
2.7239957857491083e-05, 1.0021020474147462e-05, 3.6865274119969525e-06, |
|
|
|
}(a, wg) |
|
|
|
1.3561976441886433e-06, 4.989172314621449e-07, 1.8354139230109722e-07, |
|
|
|
|
|
|
|
} { |
|
|
|
|
|
|
|
if rate := a.Snapshot().Rate(); math.Abs(want-rate) > epsilon { |
|
|
|
|
|
|
|
t.Errorf("%d minute a.Snapshot().Rate(): %f != %v\n", i, want, rate) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
elapseMinute(a) |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
wg.Wait() |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func TestEWMA5(t *testing.T) { |
|
|
|
func testEWMA(t *testing.T, alpha float64) { |
|
|
|
a := NewEWMA5() |
|
|
|
r := rand.New(rand.NewSource(time.Now().Unix())) |
|
|
|
a.Update(3) |
|
|
|
a := NewEWMA(alpha, time.Second) |
|
|
|
a.Tick() |
|
|
|
|
|
|
|
for i, want := range []float64{ |
|
|
|
// Base case.
|
|
|
|
0.6, 0.49123845184678905, 0.4021920276213837, 0.32928698165641596, |
|
|
|
|
|
|
|
0.269597378470333, 0.2207276647028654, 0.18071652714732128, |
|
|
|
if rate := a.Snapshot().Rate(); rate != 0 { |
|
|
|
0.14795817836496392, 0.12113791079679326, 0.09917933293295193, |
|
|
|
t.Errorf("(A) Base Case a.rate(): 0 != %v\n", rate) |
|
|
|
0.08120116994196763, 0.06648189501740036, 0.05443077197364752, |
|
|
|
} |
|
|
|
0.04456414692860035, 0.03648603757513079, 0.0298722410207183831020718428, |
|
|
|
a.Update(10) |
|
|
|
} { |
|
|
|
if rate := a.Snapshot().Rate(); rate != 0 { |
|
|
|
if rate := a.Snapshot().Rate(); math.Abs(want-rate) > epsilon { |
|
|
|
t.Errorf("(B) Base Case a.rate(): 0 != %v\n", rate) |
|
|
|
t.Errorf("%d minute a.Snapshot().Rate(): %f != %v\n", i, want, rate) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
elapseMinute(a) |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func TestEWMA15(t *testing.T) { |
|
|
|
// Recursive case.
|
|
|
|
a := NewEWMA15() |
|
|
|
|
|
|
|
a.Update(3) |
|
|
|
for i := 0; i < 100; i++ { |
|
|
|
a.Tick() |
|
|
|
rnd := r.Int63n(1000) + 1 |
|
|
|
for i, want := range []float64{ |
|
|
|
td, _ := NewEWMA(alpha, time.Second).(*StandardEWMA) |
|
|
|
0.6, 0.5613041910189706, 0.5251039914257684, 0.4912384518467888184678905, |
|
|
|
|
|
|
|
0.459557003018789, 0.4299187863442732, 0.4021920276213831, |
|
|
|
td.Update(10) |
|
|
|
0.37625345116383313, 0.3519877317060185, 0.3292869816564153165641596, |
|
|
|
td.addToTimestamp(-time.Duration(rnd) * time.Second) |
|
|
|
0.3080502714195546, 0.2881831806538789, 0.26959737847033216, |
|
|
|
expect := math.Pow(1-alpha, float64(rnd-1)) * 10.00 |
|
|
|
0.2522102307052083, 0.23594443252115815, 0.2207276647028646247028654470286553, |
|
|
|
if rate := td.rate(); math.Abs(rate-expect) > 0.001 { |
|
|
|
} { |
|
|
|
t.Fatalf("(A) Recursive Case a.rate(): %v != %v\n", |
|
|
|
if rate := a.Snapshot().Rate(); math.Abs(want-rate) > epsilon { |
|
|
|
expect, rate) |
|
|
|
t.Errorf("%d minute a.Snapshot().Rate(): %f != %v\n", i, want, rate) |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
expect = alpha*25 + (1-alpha)*expect |
|
|
|
|
|
|
|
td.Update(25) |
|
|
|
|
|
|
|
td.addToTimestamp(-1e9) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if rate := td.Snapshot().Rate(); math.Abs(rate-expect) > 0.001 { |
|
|
|
|
|
|
|
t.Fatalf("(B) Recursive Case a.rate(): %v != %v\n", |
|
|
|
|
|
|
|
expect, rate) |
|
|
|
} |
|
|
|
} |
|
|
|
elapseMinute(a) |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func elapseMinute(a EWMA) { |
|
|
|
func TestEWMA1(t *testing.T) { |
|
|
|
for i := 0; i < 12; i++ { |
|
|
|
// 1-minute moving average.
|
|
|
|
a.Tick() |
|
|
|
testEWMA(t, 1-math.Exp(-5.0/60.0/1)) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func TestEWMA5(t *testing.T) { |
|
|
|
|
|
|
|
// 5-minute moving average.
|
|
|
|
|
|
|
|
testEWMA(t, 1-math.Exp(-5.0/60.0/5)) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func TestEWMA15(t *testing.T) { |
|
|
|
|
|
|
|
// 15-minute moving average.
|
|
|
|
|
|
|
|
testEWMA(t, 1-math.Exp(-5.0/60.0/15)) |
|
|
|
} |
|
|
|
} |
|
|
|