github.com/NVIDIA/aistore@v1.3.23-0.20240517131212-7df6609be51d/sys/cpu_linux.go (about) 1 // Package sys provides methods to read system information 2 /* 3 * Copyright (c) 2018-2023, NVIDIA CORPORATION. All rights reserved. 4 */ 5 package sys 6 7 import ( 8 "errors" 9 "io" 10 "runtime" 11 "strconv" 12 "strings" 13 14 "github.com/NVIDIA/aistore/cmn/cos" 15 "github.com/NVIDIA/aistore/cmn/nlog" 16 ) 17 18 // isContainerized returns true if the application is running 19 // inside a container(docker/lxc/k8s) 20 // 21 // How to detect being inside a container: 22 // https://stackoverflow.com/questions/20010199/how-to-determine-if-a-process-runs-inside-lxc-docker 23 func isContainerized() (yes bool) { 24 err := cos.ReadLines(rootProcess, func(line string) error { 25 if strings.Contains(line, "docker") || strings.Contains(line, "lxc") || strings.Contains(line, "kube") { 26 yes = true 27 return io.EOF 28 } 29 return nil 30 }) 31 if err != nil { 32 nlog.Errorf("Failed to read system info: %v", err) 33 } 34 return 35 } 36 37 // Returns an approximate number of CPUs allocated for the container. 38 // By default, container runs without limits and its cfs_quota_us is 39 // negative (-1). When a container starts with limited CPU usage its quota 40 // is between 0.01 CPU and the number of CPUs on the host machine. 41 // The function rounds up the calculated number. 42 func containerNumCPU() (int, error) { 43 var quota, period uint64 44 45 quotaInt, err := cos.ReadOneInt64(contCPULimit) 46 if err != nil { 47 return 0, err 48 } 49 // negative quota means 'unlimited' - all hardware CPUs are used 50 if quotaInt <= 0 { 51 return runtime.NumCPU(), nil 52 } 53 quota = uint64(quotaInt) 54 period, err = cos.ReadOneUint64(contCPUPeriod) 55 if err != nil { 56 return 0, err 57 } 58 59 if period == 0 { 60 return 0, errors.New("failed to read container CPU info") 61 } 62 63 approx := (quota + period - 1) / period 64 return int(max(approx, 1)), nil 65 } 66 67 // LoadAverage returns the system load average 68 func LoadAverage() (avg LoadAvg, err error) { 69 avg = LoadAvg{} 70 71 line, err := cos.ReadOneLine(hostLoadAvgPath) 72 if err != nil { 73 return avg, err 74 } 75 76 fields := strings.Fields(line) 77 avg.One, err = strconv.ParseFloat(fields[0], 64) 78 if err == nil { 79 avg.Five, err = strconv.ParseFloat(fields[1], 64) 80 } 81 if err == nil { 82 avg.Fifteen, err = strconv.ParseFloat(fields[2], 64) 83 } 84 85 return avg, err 86 }