From 1b848e7192b2ccbf05323777fde868c867b7e765 Mon Sep 17 00:00:00 2001 From: aman-bansal Date: Wed, 6 Jan 2021 19:08:25 +0530 Subject: [PATCH 1/2] adding percentile in histogram --- z/histogram.go | 22 +++++++++++++ z/histogram_test.go | 80 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 102 insertions(+) create mode 100644 z/histogram_test.go diff --git a/z/histogram.go b/z/histogram.go index 3e3efb1e..1e12ef4f 100644 --- a/z/histogram.go +++ b/z/histogram.go @@ -149,3 +149,25 @@ func (histogram *HistogramData) String() string { b.WriteString(" --\n") return b.String() } + +// Percentile returns the percentile value for the histogram. +// value of p should be between [0.0-1.0] +func (histogram *HistogramData) Percentile(p float64) float64 { + if histogram.Count == 0 { + // if no data return the minimum range + return histogram.Bounds[0] + } + + pval := int64(float64(histogram.Count) * p) + for i, v := range histogram.CountPerBucket { + pval = pval - v + if pval <= 0 { + if i == len(histogram.Bounds) { + break + } + return histogram.Bounds[i] + } + } + // default return should be the max range + return histogram.Bounds[len(histogram.Bounds) - 1] +} \ No newline at end of file diff --git a/z/histogram_test.go b/z/histogram_test.go new file mode 100644 index 00000000..5d9070a7 --- /dev/null +++ b/z/histogram_test.go @@ -0,0 +1,80 @@ +package z + +import ( + "github.com/stretchr/testify/require" + "math" + "testing" +) + +func TestPercentile00(t *testing.T) { + size := int(math.Ceil((float64(514) - float64(32)) / float64(4))) + bounds := make([]float64, size + 1) + for i := range bounds { + if i == 0 { + bounds[0] = 32 + continue + } + if i == size { + bounds[i] = 514 + break + } + bounds[i] = bounds[i-1] + 4 + } + + h := NewHistogramData(bounds) + for v := 16; v <= 1024; v= v+4 { + for i:=0; i < 1000; i++ { + h.Update(int64(v)) + } + } + + require.Equal(t, h.Percentile(0.0), 32.0) +} + +func TestPercentile99(t *testing.T) { + size := int(math.Ceil((float64(514) - float64(32)) / float64(4))) + bounds := make([]float64, size + 1) + for i := range bounds { + if i == 0 { + bounds[0] = 32 + continue + } + if i == size { + bounds[i] = 514 + break + } + bounds[i] = bounds[i-1] + 4 + } + h := NewHistogramData(bounds) + for v := 16; v <= 1024; v= v+4 { + for i:=0; i < 1000; i++ { + h.Update(int64(v)) + } + } + + require.Equal(t, h.Percentile(0.99), 514.0) +} + +func TestPercentile100(t *testing.T) { + size := int(math.Ceil((float64(514) - float64(32)) / float64(4))) + bounds := make([]float64, size + 1) + for i := range bounds { + if i == 0 { + bounds[0] = 32 + continue + } + if i == size { + bounds[i] = 514 + break + } + bounds[i] = bounds[i-1] + 4 + } + h := NewHistogramData(bounds) + for v := 16; v <= 1024; v= v+4 { + for i:=0; i < 1000; i++ { + h.Update(int64(v)) + } + } + require.Equal(t, h.Percentile(1.0), 514.0) +} + From a507938659bb9cf34cc4336a16e907498f13c723 Mon Sep 17 00:00:00 2001 From: aman-bansal Date: Mon, 1 Feb 2021 12:21:25 +0530 Subject: [PATCH 2/2] adding clear function to histogram --- z/histogram.go | 22 +++++++++++++++++++--- z/histogram_test.go | 24 ++++++++++++------------ 2 files changed, 31 insertions(+), 15 deletions(-) diff --git a/z/histogram.go b/z/histogram.go index 1e12ef4f..6c9a85f3 100644 --- a/z/histogram.go +++ b/z/histogram.go @@ -153,11 +153,14 @@ func (histogram *HistogramData) String() string { // Percentile returns the percentile value for the histogram. // value of p should be between [0.0-1.0] func (histogram *HistogramData) Percentile(p float64) float64 { + if histogram == nil { + return 0 + } + if histogram.Count == 0 { // if no data return the minimum range return histogram.Bounds[0] } - pval := int64(float64(histogram.Count) * p) for i, v := range histogram.CountPerBucket { pval = pval - v @@ -169,5 +172,18 @@ func (histogram *HistogramData) Percentile(p float64) float64 { } } // default return should be the max range - return histogram.Bounds[len(histogram.Bounds) - 1] -} \ No newline at end of file + return histogram.Bounds[len(histogram.Bounds)-1] +} + +// Clear reset the histogram. Helpful in situations where we need to reset the metrics +func (histogram *HistogramData) Clear() { + if histogram == nil { + return + } + + histogram.Count = 0 + histogram.CountPerBucket = make([]int64, len(histogram.Bounds)+1) + histogram.Sum = 0 + histogram.Max = 0 + histogram.Min = math.MaxInt64 +} diff --git a/z/histogram_test.go b/z/histogram_test.go index 5d9070a7..752ac5d6 100644 --- a/z/histogram_test.go +++ b/z/histogram_test.go @@ -1,14 +1,15 @@ package z import ( - "github.com/stretchr/testify/require" "math" "testing" + + "github.com/stretchr/testify/require" ) func TestPercentile00(t *testing.T) { size := int(math.Ceil((float64(514) - float64(32)) / float64(4))) - bounds := make([]float64, size + 1) + bounds := make([]float64, size+1) for i := range bounds { if i == 0 { bounds[0] = 32 @@ -22,8 +23,8 @@ func TestPercentile00(t *testing.T) { } h := NewHistogramData(bounds) - for v := 16; v <= 1024; v= v+4 { - for i:=0; i < 1000; i++ { + for v := 16; v <= 1024; v = v + 4 { + for i := 0; i < 1000; i++ { h.Update(int64(v)) } } @@ -33,7 +34,7 @@ func TestPercentile00(t *testing.T) { func TestPercentile99(t *testing.T) { size := int(math.Ceil((float64(514) - float64(32)) / float64(4))) - bounds := make([]float64, size + 1) + bounds := make([]float64, size+1) for i := range bounds { if i == 0 { bounds[0] = 32 @@ -46,18 +47,18 @@ func TestPercentile99(t *testing.T) { bounds[i] = bounds[i-1] + 4 } h := NewHistogramData(bounds) - for v := 16; v <= 1024; v= v+4 { - for i:=0; i < 1000; i++ { + for v := 16; v <= 512; v = v + 4 { + for i := 0; i < 1000; i++ { h.Update(int64(v)) } } - require.Equal(t, h.Percentile(0.99), 514.0) + require.Equal(t, h.Percentile(0.99), 512.0) } func TestPercentile100(t *testing.T) { size := int(math.Ceil((float64(514) - float64(32)) / float64(4))) - bounds := make([]float64, size + 1) + bounds := make([]float64, size+1) for i := range bounds { if i == 0 { bounds[0] = 32 @@ -70,11 +71,10 @@ func TestPercentile100(t *testing.T) { bounds[i] = bounds[i-1] + 4 } h := NewHistogramData(bounds) - for v := 16; v <= 1024; v= v+4 { - for i:=0; i < 1000; i++ { + for v := 16; v <= 1024; v = v + 4 { + for i := 0; i < 1000; i++ { h.Update(int64(v)) } } require.Equal(t, h.Percentile(1.0), 514.0) } -