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  }