2014-07-22 08:41:39 +02:00
|
|
|
package stats
|
|
|
|
|
|
|
|
import (
|
2014-07-23 05:00:12 +02:00
|
|
|
"math"
|
2014-07-22 08:41:39 +02:00
|
|
|
"math/rand"
|
2014-07-23 05:00:12 +02:00
|
|
|
"sort"
|
2014-07-22 18:26:31 +02:00
|
|
|
"testing"
|
|
|
|
"time"
|
2014-07-22 08:41:39 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
func TestPercentiles(t *testing.T) {
|
2014-07-22 18:26:31 +02:00
|
|
|
rand.Seed(time.Now().Unix())
|
|
|
|
|
2014-07-23 05:00:12 +02:00
|
|
|
testSlice(t, uniform(10000, 1), 0.5)
|
|
|
|
testSlice(t, uniform(10000, 1), 0.9)
|
|
|
|
testSlice(t, uniform(10000, 10000), 0.5)
|
|
|
|
testSlice(t, uniform(10000, 10000), 0.9)
|
2014-07-22 08:41:39 +02:00
|
|
|
}
|
|
|
|
|
2014-07-23 05:00:12 +02:00
|
|
|
func TestLogNormPercentiles(t *testing.T) {
|
|
|
|
rand.Seed(time.Now().Unix())
|
|
|
|
|
|
|
|
testSlice(t, logNorm(10000, 1), 0.5)
|
|
|
|
testSlice(t, logNorm(10000, 1), 0.9)
|
|
|
|
}
|
|
|
|
|
|
|
|
func uniform(n int, scale float64) sort.Float64Slice {
|
|
|
|
numbers := make(sort.Float64Slice, n)
|
|
|
|
|
|
|
|
for i := 0; i < n; i++ {
|
|
|
|
numbers[i] = rand.Float64() * scale
|
|
|
|
}
|
|
|
|
|
|
|
|
return numbers
|
|
|
|
}
|
|
|
|
|
|
|
|
func logNorm(n int, scale float64) sort.Float64Slice {
|
|
|
|
numbers := make(sort.Float64Slice, n)
|
|
|
|
|
|
|
|
for i := 0; i < n; i++ {
|
|
|
|
numbers[i] = math.Exp(rand.NormFloat64()) * scale
|
|
|
|
}
|
|
|
|
|
|
|
|
return numbers
|
|
|
|
}
|
|
|
|
|
|
|
|
func testSlice(t *testing.T, numbers sort.Float64Slice, percentile float64) {
|
2014-07-22 18:26:31 +02:00
|
|
|
p := NewPercentile(percentile, 256)
|
2014-07-22 08:41:39 +02:00
|
|
|
|
2014-07-23 05:00:12 +02:00
|
|
|
for i := 0; i < len(numbers); i++ {
|
|
|
|
p.AddSample(numbers[i])
|
2014-07-22 08:41:39 +02:00
|
|
|
}
|
|
|
|
|
2014-07-23 05:00:12 +02:00
|
|
|
sort.Sort(numbers)
|
2014-07-22 08:41:39 +02:00
|
|
|
got := p.Value()
|
2014-07-23 05:00:12 +02:00
|
|
|
expected := numbers[round(float64(len(numbers))*percentile)]
|
2014-07-22 18:26:31 +02:00
|
|
|
|
2014-07-23 05:00:12 +02:00
|
|
|
if got != expected {
|
|
|
|
t.Errorf("Percentile incorrect\n actual: %f\nexpected: %f\n error: %f%%\n", got, expected, (got-expected)/expected*100)
|
2014-07-22 18:26:31 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func BenchmarkPercentiles64(b *testing.B) {
|
2014-07-23 05:00:12 +02:00
|
|
|
benchmarkSlice(b, uniform(b.N, 1), 64, 0.5)
|
2014-07-22 18:26:31 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func BenchmarkPercentiles128(b *testing.B) {
|
2014-07-23 05:00:12 +02:00
|
|
|
benchmarkSlice(b, uniform(b.N, 1), 128, 0.5)
|
2014-07-22 18:26:31 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func BenchmarkPercentiles256(b *testing.B) {
|
2014-07-23 05:00:12 +02:00
|
|
|
benchmarkSlice(b, uniform(b.N, 1), 256, 0.5)
|
2014-07-22 18:26:31 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func BenchmarkPercentiles512(b *testing.B) {
|
2014-07-23 05:00:12 +02:00
|
|
|
benchmarkSlice(b, uniform(b.N, 1), 512, 0.5)
|
2014-07-22 18:26:31 +02:00
|
|
|
}
|
|
|
|
|
2014-07-23 05:00:12 +02:00
|
|
|
func BenchmarkLNPercentiles128(b *testing.B) {
|
|
|
|
benchmarkSlice(b, logNorm(b.N, 1), 128, 0.5)
|
|
|
|
}
|
2014-07-22 18:26:31 +02:00
|
|
|
|
2014-07-23 05:00:12 +02:00
|
|
|
func BenchmarkLNPercentiles256(b *testing.B) {
|
|
|
|
benchmarkSlice(b, logNorm(b.N, 1), 258, 0.5)
|
|
|
|
}
|
2014-07-22 18:26:31 +02:00
|
|
|
|
2014-07-23 05:00:12 +02:00
|
|
|
func benchmarkSlice(b *testing.B, numbers sort.Float64Slice, window int, percentile float64) {
|
|
|
|
p := NewPercentile(percentile, window)
|
2014-07-22 08:41:39 +02:00
|
|
|
|
2014-07-22 18:26:31 +02:00
|
|
|
b.ResetTimer()
|
|
|
|
for i := 0; i < b.N; i++ {
|
|
|
|
p.AddSample(numbers[i])
|
2014-07-22 08:41:39 +02:00
|
|
|
}
|
|
|
|
}
|