Skip to content

Commit 22a0417

Browse files
committed
do not use custom percentile function
1 parent d66b740 commit 22a0417

File tree

10 files changed

+30
-114
lines changed

10 files changed

+30
-114
lines changed

wasp/benchspy/direct.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"reflect"
88
"time"
99

10+
"github.com/montanaflynn/stats"
1011
"github.com/pkg/errors"
1112
"github.com/smartcontractkit/chainlink-testing-framework/wasp"
1213
)
@@ -177,7 +178,7 @@ func (g *DirectQueryExecutor) standardQuery(standardMetric StandardLoadMetric) (
177178
asMiliDuration = append(asMiliDuration, float64(response.Duration.Nanoseconds())/1_000_000)
178179
}
179180

180-
return CalculatePercentile(asMiliDuration, 0.5), nil
181+
return stats.Median(asMiliDuration)
181182
}
182183
return medianFn, nil
183184
case Percentile95Latency:
@@ -189,7 +190,7 @@ func (g *DirectQueryExecutor) standardQuery(standardMetric StandardLoadMetric) (
189190
asMiliDuration = append(asMiliDuration, float64(response.Duration.Nanoseconds())/1_000_000)
190191
}
191192

192-
return CalculatePercentile(asMiliDuration, 0.95), nil
193+
return stats.Percentile(asMiliDuration, 95)
193194
}
194195
return p95Fn, nil
195196
case ErrorRate:
@@ -248,7 +249,7 @@ func (g *DirectQueryExecutor) MarshalJSON() ([]byte, error) {
248249
}
249250

250251
// UnmarshalJSON decodes JSON data into a DirectQueryExecutor instance.
251-
// It populates the executor's fields, including queries and results,
252+
// It populates the executor's fields, including queries and results,
252253
// enabling seamless integration of JSON configurations into the executor's structure.
253254
func (g *DirectQueryExecutor) UnmarshalJSON(data []byte) error {
254255
// helper struct with QueryExecutors as json.RawMessage and QueryResults as map[string]interface{}

wasp/benchspy/metrics.go

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,9 @@
11
package benchspy
22

33
import (
4-
"math"
5-
"sort"
64
"strconv"
75
)
86

9-
// CalculatePercentile computes the specified percentile of a slice of numbers.
10-
// It is useful for statistical analysis, allowing users to understand data distributions
11-
// by retrieving values at specific percentiles, such as median or 95th percentile.
12-
func CalculatePercentile(numbers []float64, percentile float64) float64 {
13-
// Sort the slice
14-
sort.Float64s(numbers)
15-
16-
n := len(numbers)
17-
if n == 0 {
18-
panic("cannot calculate percentile of an empty slice")
19-
}
20-
if percentile < 0 || percentile > 1 {
21-
panic("percentile must be between 0 and 1")
22-
}
23-
24-
// Calculate the rank (index)
25-
rank := percentile * float64(n-1) // Use n-1 for zero-based indexing
26-
lowerIndex := int(math.Floor(rank))
27-
upperIndex := int(math.Ceil(rank))
28-
29-
// Interpolate if necessary
30-
if lowerIndex == upperIndex {
31-
return numbers[lowerIndex]
32-
}
33-
weight := rank - float64(lowerIndex)
34-
return numbers[lowerIndex]*(1-weight) + numbers[upperIndex]*weight
35-
}
36-
377
// StringSliceToFloat64Slice converts a slice of strings to a slice of float64 values.
388
// It returns an error if any string cannot be parsed as a float64, making it useful for data conversion tasks.
399
func StringSliceToFloat64Slice(s []string) ([]float64, error) {

wasp/benchspy/metrics_test.go

Lines changed: 0 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -6,75 +6,6 @@ import (
66
"github.com/stretchr/testify/assert"
77
)
88

9-
func TestBenchSpy_CalculatePercentile(t *testing.T) {
10-
t.Run("basic percentile calculations", func(t *testing.T) {
11-
numbers := []float64{1, 2, 3, 4, 5}
12-
13-
// Test median (50th percentile)
14-
assert.Equal(t, 3.0, CalculatePercentile(numbers, 0.5))
15-
16-
// Test minimum (0th percentile)
17-
assert.Equal(t, 1.0, CalculatePercentile(numbers, 0))
18-
19-
// Test maximum (100th percentile)
20-
assert.Equal(t, 5.0, CalculatePercentile(numbers, 1))
21-
})
22-
23-
t.Run("unsorted input", func(t *testing.T) {
24-
numbers := []float64{5, 2, 1, 4, 3}
25-
assert.Equal(t, 3.0, CalculatePercentile(numbers, 0.5))
26-
})
27-
28-
t.Run("interpolation cases", func(t *testing.T) {
29-
numbers := []float64{1, 2, 3, 4}
30-
31-
// Test 25th percentile (should interpolate between 1 and 2)
32-
expected25 := 1.75
33-
assert.InDelta(t, expected25, CalculatePercentile(numbers, 0.25), 0.000001)
34-
35-
// Test 75th percentile (should interpolate between 3 and 4)
36-
expected75 := 3.25
37-
assert.InDelta(t, expected75, CalculatePercentile(numbers, 0.75), 0.000001)
38-
})
39-
40-
t.Run("single element", func(t *testing.T) {
41-
numbers := []float64{42}
42-
assert.Equal(t, 42.0, CalculatePercentile(numbers, 0.5))
43-
})
44-
45-
t.Run("duplicate values", func(t *testing.T) {
46-
numbers := []float64{1, 2, 2, 3, 3, 3, 4}
47-
assert.Equal(t, 3.0, CalculatePercentile(numbers, 0.5))
48-
})
49-
50-
t.Run("panic on empty slice", func(t *testing.T) {
51-
assert.Panics(t, func() {
52-
CalculatePercentile([]float64{}, 0.5)
53-
})
54-
})
55-
56-
t.Run("panic on invalid percentile - negative", func(t *testing.T) {
57-
assert.Panics(t, func() {
58-
CalculatePercentile([]float64{1, 2, 3}, -0.1)
59-
})
60-
})
61-
62-
t.Run("panic on invalid percentile - greater than 1", func(t *testing.T) {
63-
assert.Panics(t, func() {
64-
CalculatePercentile([]float64{1, 2, 3}, 1.1)
65-
})
66-
})
67-
68-
t.Run("large dataset", func(t *testing.T) {
69-
numbers := make([]float64, 1000)
70-
for i := 0; i < 1000; i++ {
71-
numbers[i] = float64(i)
72-
}
73-
// 90th percentile of 0-999 should be 899
74-
assert.InDelta(t, 899.1, CalculatePercentile(numbers, 0.9), 0.000001)
75-
})
76-
}
77-
789
func TestBenchSpy_StringSliceToFloat64Slice(t *testing.T) {
7910
t.Run("valid conversion", func(t *testing.T) {
8011
input := []string{"1.0", "2.5", "3.14"}

wasp/examples/benchspy/loki_query_executor/loki_query_executor_test.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"testing"
88
"time"
99

10+
"github.com/montanaflynn/stats"
1011
"github.com/stretchr/testify/assert"
1112
"github.com/stretchr/testify/require"
1213

@@ -175,11 +176,13 @@ var compareMedian = func(t *testing.T, metricName string, currentAsStringSlice,
175176

176177
currentFloatSlice, err := benchspy.StringSliceToFloat64Slice(currentAsStringSlice[metricName])
177178
require.NoError(t, err, "failed to convert %s results to float64 slice", metricName)
178-
currentMedian := benchspy.CalculatePercentile(currentFloatSlice, 0.5)
179+
currentMedian, err := stats.Median(currentFloatSlice)
180+
require.NoError(t, err, "failed to calculate median for %s results", metricName)
179181

180182
previousFloatSlice, err := benchspy.StringSliceToFloat64Slice(previousAsStringSlice[metricName])
181183
require.NoError(t, err, "failed to convert %s results to float64 slice", metricName)
182-
previousMedian := benchspy.CalculatePercentile(previousFloatSlice, 0.5)
184+
previousMedian, err := stats.Median(previousFloatSlice)
185+
require.NoError(t, err, "failed to calculate median for %s results", metricName)
183186

184187
var diffPrecentage float64
185188
if previousMedian != 0.0 && currentMedian != 0.0 {

wasp/examples/benchspy/two_query_executors/loki_and_direct_comparison_test.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"testing"
99
"time"
1010

11+
"github.com/montanaflynn/stats"
1112
"github.com/stretchr/testify/assert"
1213
"github.com/stretchr/testify/require"
1314

@@ -73,11 +74,14 @@ func TestBenchSpy_Standard_Direct_And_Loki_Metrics(t *testing.T) {
7374

7475
lokiFloatSlice, err := benchspy.StringSliceToFloat64Slice(currentAsLokiSlices[string(benchspy.MedianLatency)])
7576
require.NoError(t, err, "failed to convert %s results to float64 slice", string(benchspy.MedianLatency))
76-
lokiMedian := benchspy.CalculatePercentile(lokiFloatSlice, 0.5)
77+
lokiMedian, err := stats.Median(lokiFloatSlice)
78+
require.NoError(t, err, "failed to calculate median for loki %s results", string(benchspy.MedianLatency))
7779

7880
compareValues(t, string(benchspy.MedianLatency), lokiMedian, currentAsDirectFloats[string(benchspy.MedianLatency)], 1.0)
7981

80-
lokip95 := benchspy.CalculatePercentile(lokiFloatSlice, 0.95)
82+
lokip95, err := stats.Percentile(lokiFloatSlice, 95)
83+
require.NoError(t, err, "failed to calculate 95th percentile for loki %s results", string(benchspy.Percentile95Latency))
84+
8185
// here the max diff is 1.5% because of higher impact of data aggregation in loki
8286
compareValues(t, string(benchspy.Percentile95Latency), lokip95, currentAsDirectFloats[string(benchspy.Percentile95Latency)], 1.5)
8387

wasp/examples/benchspy/two_query_executors/two_query_executors_test.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"testing"
88
"time"
99

10+
"github.com/montanaflynn/stats"
1011
"github.com/prometheus/common/model"
1112
"github.com/stretchr/testify/assert"
1213
"github.com/stretchr/testify/require"
@@ -117,11 +118,13 @@ var compareMedian = func(t *testing.T, metricName string, currentAsStringSlice,
117118

118119
currentFloatSlice, err := benchspy.StringSliceToFloat64Slice(currentAsStringSlice[metricName])
119120
require.NoError(t, err, "failed to convert %s results to float64 slice", metricName)
120-
currentMedian := benchspy.CalculatePercentile(currentFloatSlice, 0.5)
121+
currentMedian, err := stats.Median(currentFloatSlice)
122+
require.NoError(t, err, "failed to calculate median for %s results", metricName)
121123

122124
previousFloatSlice, err := benchspy.StringSliceToFloat64Slice(previousAsStringSlice[metricName])
123125
require.NoError(t, err, "failed to convert %s results to float64 slice", metricName)
124-
previousMedian := benchspy.CalculatePercentile(previousFloatSlice, 0.5)
126+
previousMedian, err := stats.Median(previousFloatSlice)
127+
require.NoError(t, err, "failed to calculate median for %s results", metricName)
125128

126129
var diffPrecentage float64
127130
if previousMedian != 0.0 && currentMedian != 0.0 {

wasp/examples/go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ replace github.com/smartcontractkit/chainlink-testing-framework/wasp => ../
99
require (
1010
github.com/K-Phoen/grabana v0.22.2
1111
github.com/go-resty/resty/v2 v2.15.3
12+
github.com/montanaflynn/stats v0.7.1
1213
github.com/prometheus/common v0.60.0
1314
github.com/smartcontractkit/chainlink-testing-framework/wasp v1.50.1
1415
github.com/stretchr/testify v1.9.0

wasp/examples/go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -728,6 +728,8 @@ github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjY
728728
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0=
729729
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4=
730730
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
731+
github.com/montanaflynn/stats v0.7.1 h1:etflOAAHORrCC44V+aR6Ftzort912ZU+YLiSTuV8eaE=
732+
github.com/montanaflynn/stats v0.7.1/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow=
731733
github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
732734
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
733735
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=

wasp/go.mod

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ require (
111111
github.com/pelletier/go-toml/v2 v2.2.3 // indirect
112112
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
113113
github.com/prometheus/alertmanager v0.26.0 // indirect
114-
github.com/prometheus/client_golang v1.20.5 // indirect
114+
github.com/prometheus/client_golang v1.20.5
115115
github.com/prometheus/client_model v0.6.1 // indirect
116116
github.com/prometheus/common/sigv4 v0.1.0 // indirect
117117
github.com/prometheus/exporter-toolkit v0.10.1-0.20230714054209-2f4150c63f97 // indirect
@@ -141,7 +141,7 @@ require (
141141
golang.org/x/mod v0.21.0 // indirect
142142
golang.org/x/net v0.30.0 // indirect
143143
golang.org/x/oauth2 v0.23.0 // indirect
144-
golang.org/x/sync v0.8.0 // indirect
144+
golang.org/x/sync v0.8.0
145145
golang.org/x/sys v0.26.0 // indirect
146146
golang.org/x/term v0.25.0 // indirect
147147
golang.org/x/text v0.19.0 // indirect
@@ -166,6 +166,7 @@ replace github.com/smartcontractkit/chainlink-testing-framework/lib => ../lib
166166
require (
167167
github.com/coder/websocket v1.8.12
168168
github.com/grafana/pyroscope-go v1.1.2
169+
github.com/montanaflynn/stats v0.7.1
169170
github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.18
170171
github.com/smartcontractkit/chainlink-testing-framework/lib/grafana v1.50.0
171172
)

wasp/go.sum

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,8 @@ github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBa
8686
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
8787
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
8888
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
89-
github.com/OneOfOne/xxhash v1.2.8 h1:31czK/TI9sNkxIKfaUfGlU47BAxQ0ztGgd9vPyqimf8=
90-
github.com/OneOfOne/xxhash v1.2.8/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q=
89+
github.com/OneOfOne/xxhash v1.2.6 h1:U68crOE3y3MPttCMQGywZOLrTeF5HHJ3/vDBCJn9/bA=
90+
github.com/OneOfOne/xxhash v1.2.6/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q=
9191
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
9292
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
9393
github.com/Workiva/go-datastructures v1.1.0 h1:hu20UpgZneBhQ3ZvwiOGlqJSKIosin2Rd5wAKUHEO/k=
@@ -732,6 +732,8 @@ github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjY
732732
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0=
733733
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4=
734734
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
735+
github.com/montanaflynn/stats v0.7.1 h1:etflOAAHORrCC44V+aR6Ftzort912ZU+YLiSTuV8eaE=
736+
github.com/montanaflynn/stats v0.7.1/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow=
735737
github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
736738
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
737739
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
@@ -866,8 +868,6 @@ github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6Mwd
866868
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
867869
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
868870
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
869-
github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.18 h1:a3xetGZh2nFO1iX5xd9OuqiCkgbWLvW6fTN6fgVubPo=
870-
github.com/smartcontractkit/chainlink-testing-framework/lib v1.50.18/go.mod h1:NwmlNKqrb02v4Sci4b5KW644nfH2BW+FrKbWwTN5r6M=
871871
github.com/smartcontractkit/chainlink-testing-framework/lib/grafana v1.50.0 h1:VIxK8u0Jd0Q/VuhmsNm6Bls6Tb31H/sA3A/rbc5hnhg=
872872
github.com/smartcontractkit/chainlink-testing-framework/lib/grafana v1.50.0/go.mod h1:lyAu+oMXdNUzEDScj2DXB2IueY+SDXPPfyl/kb63tMM=
873873
github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js=

0 commit comments

Comments
 (0)