diff --git a/stats/percentile.go b/stats/percentile.go index 1b9e1f0..3f06d52 100644 --- a/stats/percentile.go +++ b/stats/percentile.go @@ -19,9 +19,19 @@ type Percentile struct { value uint64 // These bits are really a float64. } -// NewPercentile returns a Percentile with a given threshold +// NewPercentile returns a Percentile with a given threshold. +func NewPercentile(percentile float64) *Percentile { + return &Percentile{ + percentile: percentile, + + // 256 samples is fast, and accurate for most distributions. + values: make([]float64, 0, 256), + } +} + +// NewPercentileWithWindow returns a Percentile with a given threshold // and window size (accuracy). -func NewPercentile(percentile float64, sampleWindow int) *Percentile { +func NewPercentileWithWindow(percentile float64, sampleWindow int) *Percentile { return &Percentile{ percentile: percentile, values: make([]float64, 0, sampleWindow), diff --git a/stats/percentile_test.go b/stats/percentile_test.go index 2d01a4c..569f051 100644 --- a/stats/percentile_test.go +++ b/stats/percentile_test.go @@ -45,7 +45,7 @@ func logNorm(n int, scale float64) sort.Float64Slice { } func testSlice(t *testing.T, numbers sort.Float64Slice, percentile float64) { - p := NewPercentile(percentile, 256) + p := NewPercentile(percentile) for i := 0; i < len(numbers); i++ { p.AddSample(numbers[i]) @@ -53,10 +53,10 @@ func testSlice(t *testing.T, numbers sort.Float64Slice, percentile float64) { sort.Sort(numbers) got := p.Value() - expected := numbers[round(float64(len(numbers))*percentile)] + index := round(float64(len(numbers)) * percentile) - if got != expected { - t.Errorf("Percentile incorrect\n actual: %f\nexpected: %f\n error: %f%%\n", got, expected, (got-expected)/expected*100) + if got != numbers[index] && got != numbers[index-1] && got != numbers[index+1] { + t.Errorf("Percentile incorrect\n actual: %f\nexpected: %f, %f, %f\n", got, numbers[index-1], numbers[index], numbers[index+1]) } } @@ -85,7 +85,7 @@ func BenchmarkLNPercentiles256(b *testing.B) { } func benchmarkSlice(b *testing.B, numbers sort.Float64Slice, window int, percentile float64) { - p := NewPercentile(percentile, window) + p := NewPercentileWithWindow(percentile, window) b.ResetTimer() for i := 0; i < b.N; i++ { diff --git a/stats/stats.go b/stats/stats.go index a4b28c3..7f5d87e 100644 --- a/stats/stats.go +++ b/stats/stats.go @@ -101,9 +101,9 @@ func New(chanSize int) *Stats { responseTimeEvents: make(chan time.Duration, chanSize), ResponseTime: PercentileTimes{ - P50: NewPercentile(0.5, 128), - P90: NewPercentile(0.9, 128), - P95: NewPercentile(0.95, 128), + P50: NewPercentile(0.5), + P90: NewPercentile(0.9), + P95: NewPercentile(0.95), }, }