github.com/go-graphite/carbonapi@v0.17.0/expr/functions/weightedAverage/function_test.go (about) 1 package weightedAverage 2 3 import ( 4 "context" 5 "math" 6 "testing" 7 "time" 8 9 "github.com/go-graphite/carbonapi/expr/interfaces" 10 "github.com/go-graphite/carbonapi/expr/metadata" 11 "github.com/go-graphite/carbonapi/expr/types" 12 "github.com/go-graphite/carbonapi/pkg/parser" 13 th "github.com/go-graphite/carbonapi/tests" 14 ) 15 16 var None = math.NaN() 17 18 var ( 19 md []interfaces.FunctionMetadata = New("") 20 ) 21 22 func init() { 23 for _, m := range md { 24 metadata.RegisterFunction(m.Name, m.F) 25 } 26 } 27 28 func TestWeightedAverage(t *testing.T) { 29 now32 := int64(time.Now().Unix()) 30 31 tests := []th.EvalTestItem{ 32 { 33 "weightedAverage(metric*, metric*, 0)", 34 map[parser.MetricRequest][]*types.MetricData{ 35 {Metric: "metric*", From: 0, Until: 1}: {}, 36 }, 37 []*types.MetricData{}, 38 }, 39 { 40 "weightedAverage(metric*, metric*, 0)", 41 map[parser.MetricRequest][]*types.MetricData{ 42 {Metric: "metric*", From: 0, Until: 1}: { 43 types.MakeMetricData("metric1", []float64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}, 1, now32), 44 types.MakeMetricData("metric2", []float64{None, 2, None, 4, None, 6, None, 8, None, 10, None, 12, None, 14, None, 16, None, 18, None, 20}, 1, now32), 45 types.MakeMetricData("metric3", []float64{1, 2, None, None, None, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, None, None, None}, 1, now32), 46 types.MakeMetricData("metric4", []float64{1, 2, 3, 4, None, 6, None, None, 9, 10, 11, None, 13, None, None, None, None, 18, 19, 20}, 1, now32), 47 types.MakeMetricData("metric5", []float64{1, 2, None, None, None, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, None, None}, 1, now32), 48 }, 49 }, 50 []*types.MetricData{types.MakeMetricData( 51 "weightedAverage(metric*, metric*, 0)", []float64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}, 1, now32), 52 }, 53 }, 54 { 55 "weightedAverage(metric*.dividend, metric*.divisor, 0)", 56 map[parser.MetricRequest][]*types.MetricData{ 57 {Metric: "metric*.dividend", From: 0, Until: 1}: { 58 types.MakeMetricData("metric1.dividend", []float64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}, 1, now32), 59 types.MakeMetricData("metric2.dividend", []float64{None, 2, None, 4, None, 6, None, 8, None, 10, None, 12, None, 14, None, 16, None, 18, None, 20}, 1, now32), 60 types.MakeMetricData("metric3.dividend", []float64{1, 2, None, None, None, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, None, None, None}, 1, now32), 61 types.MakeMetricData("metric5.dividend", []float64{1, 2, None, None, None, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, None, None}, 1, now32), 62 }, 63 {Metric: "metric*.divisor", From: 0, Until: 1}: { 64 types.MakeMetricData("metric1.divisor", []float64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}, 1, now32), 65 types.MakeMetricData("metric3.divisor", []float64{1, 2, None, None, None, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, None, None, None}, 1, now32), 66 types.MakeMetricData("metric4.divisor", []float64{1, 2, 3, 4, None, 6, None, None, 9, 10, 11, None, 13, None, None, None, None, 18, 19, 20}, 1, now32), 67 types.MakeMetricData("metric5.divisor", []float64{1, 2, None, None, None, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, None, None}, 1, now32), 68 }, 69 }, 70 []*types.MetricData{types.MakeMetricData( 71 "weightedAverage(metric*.dividend, metric*.divisor, 0)", 72 []float64{0.75, 1.5, 1.5, 2.0, 5.0, 4.5, 7.0, 8.0, 6.75, 7.5, 8.25, 12.0, 9.75, 14.0, 15.0, 16.0, 17.0, 12.0, 9.5, 10.0}, 1, now32, 73 ), 74 }, 75 }, 76 { 77 "weightedAverage(metric1.dividend, metric2.divisor, 0)", 78 map[parser.MetricRequest][]*types.MetricData{ 79 {Metric: "metric1.dividend", From: 0, Until: 1}: { 80 types.MakeMetricData("metric1.dividend", []float64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}, 1, now32), 81 }, 82 {Metric: "metric2.divisor", From: 0, Until: 1}: { 83 types.MakeMetricData("metric2.divisor", []float64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}, 1, now32), 84 }, 85 }, 86 []*types.MetricData{}, 87 }, 88 } 89 90 for _, tt := range tests { 91 testName := tt.Target 92 t.Run(testName, func(t *testing.T) { 93 eval := th.EvaluatorFromFunc(md[0].F) 94 th.TestEvalExpr(t, eval, &tt) 95 }) 96 } 97 98 } 99 100 func BenchmarkWeightedAverage(b *testing.B) { 101 now32 := time.Now().Unix() 102 103 benchmarks := []struct { 104 target string 105 M map[parser.MetricRequest][]*types.MetricData 106 }{ 107 { 108 target: "weightedAverage(metric*, metric*, 0)", 109 M: map[parser.MetricRequest][]*types.MetricData{ 110 {Metric: "metric*", From: 0, Until: 1}: { 111 types.MakeMetricData("metric1", []float64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}, 1, now32), 112 types.MakeMetricData("metric2", []float64{None, 2, None, 4, None, 6, None, 8, None, 10, None, 12, None, 14, None, 16, None, 18, None, 20}, 1, now32), 113 types.MakeMetricData("metric3", []float64{1, 2, None, None, None, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, None, None, None}, 1, now32), 114 types.MakeMetricData("metric4", []float64{1, 2, 3, 4, None, 6, None, None, 9, 10, 11, None, 13, None, None, None, None, 18, 19, 20}, 1, now32), 115 types.MakeMetricData("metric5", []float64{1, 2, None, None, None, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, None, None}, 1, now32), 116 }, 117 }, 118 }, 119 { 120 target: "weightedAverage(metric*.dividend, metric*.divisor, 0)", 121 M: map[parser.MetricRequest][]*types.MetricData{ 122 {Metric: "metric*.dividend", From: 0, Until: 1}: { 123 types.MakeMetricData("metric1.dividend", []float64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}, 1, now32), 124 types.MakeMetricData("metric2.dividend", []float64{None, 2, None, 4, None, 6, None, 8, None, 10, None, 12, None, 14, None, 16, None, 18, None, 20}, 1, now32), 125 types.MakeMetricData("metric3.dividend", []float64{1, 2, None, None, None, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, None, None, None}, 1, now32), 126 types.MakeMetricData("metric5.dividend", []float64{1, 2, None, None, None, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, None, None}, 1, now32), 127 }, 128 {Metric: "metric*.divisor", From: 0, Until: 1}: { 129 types.MakeMetricData("metric1.divisor", []float64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}, 1, now32), 130 types.MakeMetricData("metric3.divisor", []float64{1, 2, None, None, None, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, None, None, None}, 1, now32), 131 types.MakeMetricData("metric4.divisor", []float64{1, 2, 3, 4, None, 6, None, None, 9, 10, 11, None, 13, None, None, None, None, 18, 19, 20}, 1, now32), 132 types.MakeMetricData("metric5.divisor", []float64{1, 2, None, None, None, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, None, None}, 1, now32), 133 }, 134 }, 135 }, 136 { 137 // empty result 138 target: "weightedAverage(metric1.dividend, metric2.divisor, 0)", 139 M: map[parser.MetricRequest][]*types.MetricData{ 140 {Metric: "metric1.dividend", From: 0, Until: 1}: { 141 types.MakeMetricData("metric1.dividend", []float64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}, 1, now32), 142 }, 143 {Metric: "metric2.divisor", From: 0, Until: 1}: { 144 types.MakeMetricData("metric2.divisor", []float64{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}, 1, now32), 145 }, 146 }, 147 }, 148 } 149 150 eval := th.EvaluatorFromFunc(md[0].F) 151 152 for _, bm := range benchmarks { 153 b.Run(bm.target, func(b *testing.B) { 154 exp, _, err := parser.ParseExpr(bm.target) 155 if err != nil { 156 b.Fatalf("failed to parse %s: %+v", bm.target, err) 157 } 158 159 b.ResetTimer() 160 161 for i := 0; i < b.N; i++ { 162 g, err := eval.Eval(context.Background(), exp, 0, 1, bm.M) 163 if err != nil { 164 b.Fatalf("failed to eval %s: %+v", bm.target, err) 165 } 166 _ = g 167 } 168 }) 169 } 170 }