k8s.io/perf-tests/clusterloader2@v0.0.0-20240304094227-64bdb12da87e/pkg/measurement/common/network/performance-measurement-helper.go (about) 1 /* 2 Copyright 2021 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package network 18 19 import ( 20 "encoding/json" 21 "fmt" 22 "math" 23 "sort" 24 25 "k8s.io/apimachinery/pkg/runtime/schema" 26 "k8s.io/client-go/dynamic" 27 "k8s.io/client-go/dynamic/dynamicinformer" 28 "k8s.io/client-go/tools/cache" 29 "k8s.io/perf-tests/clusterloader2/pkg/measurement" 30 "k8s.io/perf-tests/clusterloader2/pkg/util" 31 ) 32 33 func (npm *networkPerformanceMeasurement) validate(config *measurement.Config) error { 34 var err error 35 if npm.testDuration, err = util.GetDuration(config.Params, "duration"); err != nil { 36 return err 37 } 38 if npm.protocol, err = util.GetString(config.Params, "protocol"); err != nil { 39 return err 40 } 41 if npm.protocol != protocolTCP && npm.protocol != protocolUDP && npm.protocol != protocolHTTP { 42 return fmt.Errorf("invalid protocol , supported ones are TCP,UDP,HTTP") 43 } 44 if err = npm.validatePodConfiguration(config); err != nil { 45 return err 46 } 47 npm.podRatioType = npm.getPodRatioType() 48 return nil 49 } 50 51 func (npm *networkPerformanceMeasurement) validatePodConfiguration(config *measurement.Config) error { 52 var err error 53 if npm.numberOfClients, err = util.GetInt(config.Params, "numberOfClients"); err != nil { 54 return err 55 } 56 if npm.numberOfServers, err = util.GetInt(config.Params, "numberOfServers"); err != nil { 57 return err 58 } 59 if npm.numberOfClients <= 0 || npm.numberOfServers <= 0 { 60 return fmt.Errorf("invalid number of client or server pods") 61 } 62 return nil 63 } 64 65 func (npm *networkPerformanceMeasurement) getPodRatioType() string { 66 if npm.numberOfClients == npm.numberOfServers && npm.numberOfClients == 1 { 67 return oneToOne 68 } 69 if (npm.numberOfClients > npm.numberOfServers) && npm.numberOfServers == 1 { 70 return manyToOne 71 } 72 if npm.numberOfClients == npm.numberOfServers { 73 return manyToMany 74 } 75 return invalid 76 } 77 78 func (npm *networkPerformanceMeasurement) populateTemplate(podPair podPair, index int) map[string]interface{} { 79 return map[string]interface{}{ 80 "index": index, 81 "clientPodName": podPair.sourcePodName, 82 "serverPodName": podPair.destinationPodName, 83 "clientPodIP": podPair.sourcePodIP, 84 "serverPodIP": podPair.destinationPodIP, 85 "protocol": npm.protocol, 86 "duration": npm.testDuration.Seconds(), 87 "clientStartTimestamp": npm.startTimeStampForTestExecution, 88 "numberOfClients": 1, 89 } 90 } 91 92 func getInformer(namespace string, k8sClient dynamic.Interface, gvr schema.GroupVersionResource) (cache.SharedInformer, error) { 93 dynamicInformerFactory := dynamicinformer.NewFilteredDynamicSharedInformerFactory(k8sClient, 0, namespace, nil) 94 informer := dynamicInformerFactory.ForResource(gvr).Informer() 95 return informer, nil 96 } 97 98 type metricPercentiles struct { 99 percentile05 float64 100 percentile50 float64 101 percentile95 float64 102 } 103 104 type float64Slice []float64 105 106 func (p float64Slice) Len() int { return len(p) } 107 func (p float64Slice) Less(i, j int) bool { return p[i] < p[j] } 108 func (p float64Slice) Swap(i, j int) { p[i], p[j] = p[j], p[i] } 109 110 func getPercentile(values float64Slice) metricPercentiles { 111 length := len(values) 112 if length == 0 { 113 return metricPercentiles{0, 0, 0} 114 } 115 sort.Float64s(values) 116 perc05 := values[int(math.Ceil(float64(length*05)/100))-1] 117 perc50 := values[int(math.Ceil(float64(length*50)/100))-1] 118 perc95 := values[int(math.Ceil(float64(length*95)/100))-1] 119 return metricPercentiles{percentile05: perc05, percentile50: perc50, percentile95: perc95} 120 } 121 122 func getMetricResponse(metricMap map[string]interface{}, response *metricResponse) error { 123 body, err := json.Marshal(metricMap) 124 if err != nil { 125 return fmt.Errorf("error marshaling metricMap : %s", err) 126 } 127 if err = json.Unmarshal(body, response); err != nil { 128 return fmt.Errorf("error un-marshaling onto metricResponse: %s", err) 129 } 130 return nil 131 }