github.com/matrixorigin/matrixone@v1.2.0/pkg/util/trace/impl/motrace/cu.go (about) 1 // Copyright 2024 Matrix Origin 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package motrace 16 17 import ( 18 "github.com/matrixorigin/matrixone/pkg/config" 19 "github.com/matrixorigin/matrixone/pkg/container/types" 20 "github.com/matrixorigin/matrixone/pkg/logutil" 21 "github.com/matrixorigin/matrixone/pkg/util/trace/impl/motrace/statistic" 22 23 "go.uber.org/zap" 24 ) 25 26 // DecimalNSThreshold default 100 sec 27 const DecimalNSThreshold = 100e9 28 29 func CalculateCUWithCfg(stats statistic.StatsArray, durationNS int64, cfg *config.OBCUConfig) float64 { 30 31 if cfg == nil { 32 cfg = GetCUConfig() 33 } 34 // basic 35 cpu := stats.GetTimeConsumed() * cfg.CpuPrice 36 ioIn := stats.GetS3IOInputCount() * cfg.IoInPrice 37 ioOut := stats.GetS3IOOutputCount() * cfg.IoOutPrice 38 connType := stats.GetConnType() 39 traffic := 0.0 40 switch statistic.ConnType(connType) { 41 case statistic.ConnTypeUnknown: 42 traffic = stats.GetOutTrafficBytes() * cfg.TrafficPrice0 43 case statistic.ConnTypeInternal: 44 traffic = stats.GetOutTrafficBytes() * cfg.TrafficPrice1 45 case statistic.ConnTypeExternal: 46 traffic = stats.GetOutTrafficBytes() * cfg.TrafficPrice2 47 default: 48 logutil.Warn("Unknown ConnType as CU", zap.Float64("connType", connType)) 49 } 50 51 if durationNS <= DecimalNSThreshold { 52 mem := stats.GetMemorySize() * float64(durationNS) * cfg.MemPrice 53 return (cpu + mem + ioIn + ioOut + traffic) / cfg.CUUnit 54 } else { 55 memCU := CalculateCUMem(int64(stats.GetMemorySize()), durationNS, cfg) 56 return (cpu+ioIn+ioOut+traffic)/cfg.CUUnit + memCU 57 58 } 59 } 60 61 // CalculateCU calculate CU cost 62 // the result only keep 3 decimal places 63 // Tips: CU is long-tailed numbers 64 func CalculateCU(stats statistic.StatsArray, durationNS int64) float64 { 65 cfg := GetCUConfig() 66 return CalculateCUWithCfg(stats, durationNS, cfg) 67 } 68 69 // CalculateCUv1 calculate CU cost 70 func CalculateCUv1(stats statistic.StatsArray, durationNS int64) float64 { 71 cfg := GetCUConfigV1() 72 return CalculateCUWithCfg(stats, durationNS, cfg) 73 } 74 75 // CalculateCUCpu 76 // Be careful of the number overflow 77 func CalculateCUCpu(cpuRuntimeNS int64, cfg *config.OBCUConfig) float64 { 78 if cfg == nil { 79 cfg = GetCUConfig() 80 } 81 return float64(cpuRuntimeNS) / cfg.CUUnit * cfg.CpuPrice 82 } 83 84 // CalculateCUMem 85 // Be careful of the number overflow 86 func CalculateCUMem(memByte int64, durationNS int64, cfg *config.OBCUConfig) float64 { 87 if cfg == nil { 88 cfg = GetCUConfig() 89 } 90 if durationNS > DecimalNSThreshold { 91 val, err := CalculateCUMemDecimal(memByte, durationNS, cfg.MemPrice, cfg.CUUnit) 92 if err == nil { 93 return val 94 } 95 } 96 // float64 has 52 bits for number, so it can represent 15 digits valid number 97 return float64(durationNS) / cfg.CUUnit * cfg.MemPrice * float64(memByte) 98 } 99 100 const Decimal128ScalePrice = 26 101 102 func convertFloat64ToDecimal128Price(val float64) (types.Decimal128, error) { 103 return types.Decimal128FromFloat64(val, Decimal128Width, Decimal128ScalePrice) 104 } 105 106 func CalculateCUMemDecimal(memByte, durationNS int64, memPrice, cuUnit float64) (float64, error) { 107 price := mustDecimal128(convertFloat64ToDecimal128Price(memPrice)) 108 unit := mustDecimal128(convertFloat64ToDecimal128Price(cuUnit)) 109 110 val1 := types.Decimal256FromInt64(memByte) 111 val2 := types.Decimal256FromInt64(durationNS) 112 val3 := types.Decimal256FromDecimal128(price) 113 val4 := types.Decimal256FromDecimal128(unit) 114 cuScale := int32(Decimal128ScalePrice) 115 var err error 116 val1, err = val1.Mul256(val2) 117 if err != nil { 118 return 0, err 119 } 120 val1, err = val1.Mul256(val3) 121 if err != nil { 122 return 0, err 123 } 124 val1, err = val1.Scale(cuScale) 125 if err != nil { 126 return 0, err 127 } 128 val1, err = val1.Div256(val4) 129 if err != nil { 130 return 0, err 131 } 132 133 return types.Decimal256ToFloat64(val1, cuScale), nil 134 } 135 136 func CalculateCUIOIn(ioCnt int64, cfg *config.OBCUConfig) float64 { 137 if cfg == nil { 138 cfg = GetCUConfig() 139 } 140 return float64(ioCnt) * cfg.IoInPrice / cfg.CUUnit 141 } 142 143 func CalculateCUIOOut(ioCnt int64, cfg *config.OBCUConfig) float64 { 144 if cfg == nil { 145 cfg = GetCUConfig() 146 } 147 return float64(ioCnt) * cfg.IoOutPrice / cfg.CUUnit 148 } 149 150 func CalculateCUTraffic(bytes int64, connType float64, cfg *config.OBCUConfig) float64 { 151 if cfg == nil { 152 cfg = GetCUConfig() 153 } 154 traffic := 0.0 155 switch statistic.ConnType(connType) { 156 case statistic.ConnTypeUnknown: 157 traffic = float64(bytes) * cfg.TrafficPrice0 158 case statistic.ConnTypeInternal: 159 traffic = float64(bytes) * cfg.TrafficPrice1 160 case statistic.ConnTypeExternal: 161 traffic = float64(bytes) * cfg.TrafficPrice2 162 default: 163 traffic = float64(bytes) * cfg.TrafficPrice0 164 } 165 return traffic / cfg.CUUnit 166 } 167 168 var cuCfg = config.NewOBCUConfig() 169 var cuCfgV1 = config.NewOBCUConfig() 170 171 func GetCUConfig() *config.OBCUConfig { 172 return cuCfg 173 } 174 175 func GetCUConfigV1() *config.OBCUConfig { 176 return cuCfgV1 177 } 178 179 func SetCuConfig(cu, cuv1 *config.OBCUConfig) { 180 cuCfg, cuCfgV1 = cu, cuv1 181 }