k8s.io/perf-tests/clusterloader2@v0.0.0-20240304094227-64bdb12da87e/pkg/measurement/util/resource.go (about) 1 /* 2 Copyright 2018 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 util 18 19 import ( 20 "math" 21 "sort" 22 "time" 23 ) 24 25 // ContainerResourceUsage represents resource usage by a single container. 26 type ContainerResourceUsage struct { 27 Name string 28 Timestamp time.Time 29 CPUUsageInCores float64 30 MemoryUsageInBytes uint64 31 MemoryWorkingSetInBytes uint64 32 MemoryRSSInBytes uint64 33 // The interval used to calculate CPUUsageInCores. 34 CPUInterval time.Duration 35 } 36 37 // ResourceUsagePerContainer is a map of ContainerResourceUsage for containers. 38 type ResourceUsagePerContainer map[string]*ContainerResourceUsage 39 40 // UsageDataPerContainer contains resource usage data series. 41 type UsageDataPerContainer struct { 42 CPUData []float64 43 MemUseData []uint64 44 MemWorkSetData []uint64 45 } 46 47 // ResourceConstraint specifies constraint on resources. 48 type ResourceConstraint struct { 49 CPUConstraint float64 `json:"cpuConstraint"` 50 MemoryConstraint uint64 `json:"memoryConstraint"` 51 } 52 53 // SingleContainerSummary is a resource usage summary for a single container. 54 type SingleContainerSummary struct { 55 Name string 56 CPU float64 57 Mem uint64 58 } 59 60 type uint64arr []uint64 61 62 func (a uint64arr) Len() int { return len(a) } 63 func (a uint64arr) Swap(i, j int) { a[i], a[j] = a[j], a[i] } 64 func (a uint64arr) Less(i, j int) bool { return a[i] < a[j] } 65 66 // ComputePercentiles calculates percentiles for given data series. 67 func ComputePercentiles(timeSeries []ResourceUsagePerContainer, percentilesToCompute []int) map[int]ResourceUsagePerContainer { 68 if len(timeSeries) == 0 { 69 return make(map[int]ResourceUsagePerContainer) 70 } 71 dataMap := make(map[string]*UsageDataPerContainer) 72 for i := range timeSeries { 73 for name, data := range timeSeries[i] { 74 if dataMap[name] == nil { 75 dataMap[name] = &UsageDataPerContainer{ 76 CPUData: make([]float64, 0, len(timeSeries)), 77 MemUseData: make([]uint64, 0, len(timeSeries)), 78 MemWorkSetData: make([]uint64, 0, len(timeSeries)), 79 } 80 } 81 dataMap[name].CPUData = append(dataMap[name].CPUData, data.CPUUsageInCores) 82 dataMap[name].MemUseData = append(dataMap[name].MemUseData, data.MemoryUsageInBytes) 83 dataMap[name].MemWorkSetData = append(dataMap[name].MemWorkSetData, data.MemoryWorkingSetInBytes) 84 } 85 } 86 for _, v := range dataMap { 87 sort.Float64s(v.CPUData) 88 sort.Sort(uint64arr(v.MemUseData)) 89 sort.Sort(uint64arr(v.MemWorkSetData)) 90 } 91 92 result := make(map[int]ResourceUsagePerContainer) 93 for _, perc := range percentilesToCompute { 94 data := make(ResourceUsagePerContainer) 95 for k, v := range dataMap { 96 percentileIndex := int(math.Ceil(float64(len(v.CPUData)*perc)/100)) - 1 97 data[k] = &ContainerResourceUsage{ 98 Name: k, 99 CPUUsageInCores: v.CPUData[percentileIndex], 100 MemoryUsageInBytes: v.MemUseData[percentileIndex], 101 MemoryWorkingSetInBytes: v.MemWorkSetData[percentileIndex], 102 } 103 } 104 result[perc] = data 105 } 106 return result 107 } 108 109 // LeftMergeData merges two data structures. 110 func LeftMergeData(left, right map[int]ResourceUsagePerContainer) map[int]ResourceUsagePerContainer { 111 result := make(map[int]ResourceUsagePerContainer) 112 for percentile, data := range left { 113 result[percentile] = data 114 if _, ok := right[percentile]; !ok { 115 continue 116 } 117 for k, v := range right[percentile] { 118 result[percentile][k] = v 119 } 120 } 121 return result 122 }