github.com/go-graphite/carbonapi@v0.17.0/expr/functions/movingMedian/function_test.go (about) 1 package movingMedian 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 "github.com/go-graphite/carbonapi/tests/compare" 15 ) 16 17 var ( 18 md []interfaces.FunctionMetadata = New("") 19 ) 20 21 func init() { 22 for _, m := range md { 23 metadata.RegisterFunction(m.Name, m.F) 24 } 25 } 26 27 func TestMovingMedian(t *testing.T) { 28 now32 := int64(time.Now().Unix()) 29 30 tests := []th.EvalTestItem{ 31 { 32 "movingMedian(metric1,4)", 33 map[parser.MetricRequest][]*types.MetricData{ 34 {Metric: "metric1", From: 0, Until: 1}: {types.MakeMetricData("metric1", []float64{1, 1, 1, 1, 2, 2, 2, 4, 6, 4, 6, 8}, 1, now32)}, 35 }, 36 []*types.MetricData{types.MakeMetricData("movingMedian(metric1,4)", []float64{math.NaN(), math.NaN(), math.NaN(), 1, 1, 1.5, 2, 2, 3, 4, 5, 6}, 37 1, 0).SetTag("movingMedian", "4").SetNameTag("metric1")}, // StartTime = from 38 }, 39 { 40 "movingMedian(metric1,5)", 41 map[parser.MetricRequest][]*types.MetricData{ 42 {Metric: "metric1", From: 0, Until: 1}: {types.MakeMetricData("metric1", []float64{1, 1, 1, 1, 2, 2, 2, 4, 6, 4, 6, 8, 1, 2, math.NaN()}, 1, now32)}, 43 }, 44 []*types.MetricData{types.MakeMetricData("movingMedian(metric1,5)", []float64{math.NaN(), math.NaN(), math.NaN(), math.NaN(), 1, 1, 2, 2, 2, 4, 4, 6, 6, 4, 2}, 45 1, 0).SetTag("movingMedian", "5").SetNameTag("metric1")}, // StartTime = from 46 }, 47 { 48 "movingMedian(metric1,\"1s\")", 49 map[parser.MetricRequest][]*types.MetricData{ 50 {Metric: "metric1", From: -1, Until: 1}: {types.MakeMetricData("metric1", []float64{1, 1, 1, 1, 1, 2, 2, 2, 4, 6, 4, 6, 8, 1, 2, 0}, 1, now32)}, 51 }, 52 []*types.MetricData{types.MakeMetricData("movingMedian(metric1,'1s')", []float64{1, 1, 1, 1, 2, 2, 2, 4, 6, 4, 6, 8, 1, 2, 0}, 53 1, 0).SetTag("movingMedian", "'1s'").SetNameTag("metric1")}, // StartTime = from 54 }, 55 { 56 "movingMedian(metric1,\"3s\")", 57 map[parser.MetricRequest][]*types.MetricData{ 58 {Metric: "metric1", From: -3, Until: 1}: {types.MakeMetricData("metric1", []float64{0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 4, 6, 4, 6, 8, 1, 2}, 1, now32)}, 59 }, 60 []*types.MetricData{types.MakeMetricData("movingMedian(metric1,'3s')", []float64{0, 1, 1, 1, 1, 2, 2, 2, 4, 4, 6, 6, 6, 2}, 61 1, 0).SetTag("movingMedian", "'3s'").SetNameTag("metric1")}, // StartTime = from 62 }, 63 { 64 "movingMedian(metric1,\"5s\")", 65 map[parser.MetricRequest][]*types.MetricData{ 66 {Metric: "metric1", From: -5, Until: 1}: {types.MakeMetricData("metric1", []float64{1, 2, 3}, 10, now32)}, // step > windowSize 67 }, 68 []*types.MetricData{types.MakeMetricData("movingMedian(metric1,'5s')", []float64{math.NaN(), math.NaN(), math.NaN()}, 69 10, now32).SetTag("movingMedian", "'5s'").SetNameTag("metric1")}, // StartTime = from 70 }, 71 } 72 73 for _, tt := range tests { 74 testName := tt.Target 75 t.Run(testName, func(t *testing.T) { 76 eval := th.EvaluatorFromFunc(md[0].F) 77 th.TestEvalExpr(t, eval, &tt) 78 }) 79 } 80 81 } 82 83 func BenchmarkMovingMedian(b *testing.B) { 84 benchmarks := []struct { 85 target string 86 M map[parser.MetricRequest][]*types.MetricData 87 }{ 88 { 89 target: "movingMedian(metric1,'5s')", 90 M: map[parser.MetricRequest][]*types.MetricData{ 91 {Metric: "metric1", From: -5, Until: 1}: {types.MakeMetricData("metric1", []float64{1, 2, 3}, 10, 1)}, // step > windowSize 92 }, 93 }, 94 { 95 target: "movingMedian(metric1,4)", 96 M: map[parser.MetricRequest][]*types.MetricData{ 97 {Metric: "metric1", From: 0, Until: 1}: {types.MakeMetricData("metric1", compare.GenerateMetrics(1024, 1.0, 9.0, 1.0), 1, 1)}, 98 }, 99 }, 100 { 101 target: "movingMedian(metric1,2)", 102 M: map[parser.MetricRequest][]*types.MetricData{ 103 {Metric: "metric1", From: 0, Until: 1}: {types.MakeMetricData("metric1", compare.GenerateMetrics(1024, 1.0, 9.0, 1.0), 1, 1)}, 104 }, 105 }, 106 { 107 target: "movingMedian(metric1,600)", 108 M: map[parser.MetricRequest][]*types.MetricData{ 109 {Metric: "metric1", From: 0, Until: 1}: {types.MakeMetricData("metric1", compare.GenerateMetrics(1024, 1.0, 9.0, 1.0), 1, 1)}, 110 }, 111 }, 112 } 113 114 eval := th.EvaluatorFromFunc(md[0].F) 115 116 for _, bm := range benchmarks { 117 b.Run(bm.target, func(b *testing.B) { 118 exp, _, err := parser.ParseExpr(bm.target) 119 if err != nil { 120 b.Fatalf("failed to parse %s: %+v", bm.target, err) 121 } 122 123 b.ResetTimer() 124 125 for i := 0; i < b.N; i++ { 126 g, err := eval.Eval(context.Background(), exp, 0, 1, bm.M) 127 if err != nil { 128 b.Fatalf("failed to eval %s: %+v", bm.target, err) 129 } 130 _ = g 131 } 132 }) 133 } 134 }