package metrics import ( "math/rand" "runtime" "testing" "time" ) func TestExpDecaySample10(t *testing.T) { s := NewExpDecaySample(100, 0.99) for i := 0; i < 10; i++ { s.Update(int64(i)) } if size := s.Size(); 10 != size { t.Errorf("s.Size(): 10 != %v\n", size) } if l := len(s.Values()); 10 != l { t.Errorf("len(s.Values()): 10 != %v\n", l) } for _, v := range s.Values() { if v > 10 || v < 0 { t.Errorf("out of range [0, 10): %v\n", v) } } } func TestExpDecaySample100(t *testing.T) { s := NewExpDecaySample(1000, 0.01) for i := 0; i < 100; i++ { s.Update(int64(i)) } if size := s.Size(); 100 != size { t.Errorf("s.Size(): 100 != %v\n", size) } if l := len(s.Values()); 100 != l { t.Errorf("len(s.Values()): 100 != %v\n", l) } for _, v := range s.Values() { if v > 100 || v < 0 { t.Errorf("out of range [0, 100): %v\n", v) } } } func TestExpDecaySample1000(t *testing.T) { s := NewExpDecaySample(100, 0.99) for i := 0; i < 1000; i++ { s.Update(int64(i)) } if size := s.Size(); 100 != size { t.Errorf("s.Size(): 100 != %v\n", size) } if l := len(s.Values()); 100 != l { t.Errorf("len(s.Values()): 100 != %v\n", l) } for _, v := range s.Values() { if v > 1000 || v < 0 { t.Errorf("out of range [0, 100): %v\n", v) } } } // This test makes sure that the sample's priority is not amplified by using // nanosecond duration since start rather than second duration since start. // The priority becomes +Inf quickly after starting if this is done, // effectively freezing the set of samples until a rescale step happens. func TestExpDecaySampleNanosecondRegression(t *testing.T) { s := NewExpDecaySample(100, 0.99) for i := 0; i < 100; i++ { s.Update(10) } time.Sleep(1 * time.Millisecond) for i := 0; i < 100; i++ { s.Update(20) } v := s.Values() avg := float64(0) for i := 0; i < len(v); i++ { avg += float64(v[i]) } avg /= float64(len(v)) if avg > 16 || avg < 14 { t.Errorf("out of range [14, 16]: %v\n", avg) } } func TestUniformSample(t *testing.T) { s := NewUniformSample(100) for i := 0; i < 1000; i++ { s.Update(int64(i)) } if size := s.Size(); 100 != size { t.Errorf("s.Size(): 100 != %v\n", size) } if l := len(s.Values()); 100 != l { t.Errorf("len(s.Values()): 100 != %v\n", l) } for _, v := range s.Values() { if v > 1000 || v < 0 { t.Errorf("out of range [0, 100): %v\n", v) } } } func TestUniformSampleIncludesTail(t *testing.T) { s := NewUniformSample(100) max := 100 for i := 0; i < max; i++ { s.Update(int64(i)) } v := s.Values() sum := 0 exp := (max - 1) * max / 2 for i := 0; i < len(v); i++ { sum += int(v[i]) } if exp != sum { t.Errorf("sum: %v != %v\n", exp, sum) } } func benchmarkSample(b *testing.B, s Sample) { var m runtime.MemStats var p [2]uint64 runtime.ReadMemStats(&m) p[0] = m.PauseTotalNs for i := 0; i < b.N; i++ { s.Update(rand.Int63()) } runtime.GC() runtime.ReadMemStats(&m) p[1] = m.PauseTotalNs b.Logf("GC cost: %d ns/op", int(p[1]-p[0])/b.N) } func BenchmarkExpDecaySample257(b *testing.B) { benchmarkSample(b, NewExpDecaySample(257, 0.015)) } func BenchmarkExpDecaySample514(b *testing.B) { benchmarkSample(b, NewExpDecaySample(514, 0.015)) } func BenchmarkExpDecaySample1028(b *testing.B) { benchmarkSample(b, NewExpDecaySample(1028, 0.015)) } func BenchmarkUniformSample257(b *testing.B) { benchmarkSample(b, NewUniformSample(257)) } func BenchmarkUniformSample514(b *testing.B) { benchmarkSample(b, NewUniformSample(514)) } func BenchmarkUniformSample1028(b *testing.B) { benchmarkSample(b, NewUniformSample(1028)) }