cpuacct.go 2.2 KB
Newer Older
“李磊”'s avatar
“李磊” committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
package fs

import (
	"fmt"
	"os"
	"path/filepath"
	"strconv"
	"strings"

	"linkfog.com/public/lib/cgroup/fscommon"
	"linkfog.com/public/lib/l"
)

var (
	defaultCPU = "-1"
)

func CPUSubSystemName() string {
	return "cpuacct"
}

func GetCPULimit(cgroupDir string, defaultLimit float64) float64 {
	// parse quota
	contents, err := fscommon.GetCgroupParamString(filepath.Join(cgroupDir, "cpu.cfs_quota_us"))
	if err != nil {
		l.Errorf("read cpu.cfs_quota_us file error:%v, use default value", err)
		return defaultLimit
	}
	if contents == defaultCPU {
		l.Warn("cpu.cfs_quota_us is defaultCPU, use default value")
		return defaultLimit
	}
	cpuQuota, err := fscommon.ParseUint(contents, 10, 64)
	if err != nil {
		l.Errorf("parse cpu.cfs_quota_us error:%v, contents:%s, use default value", err, contents)
		return defaultLimit
	}
	if cpuQuota == 0 {
		l.Warn("cpu.cfs_quota_us is 0, use default value")
		return defaultLimit
	}

	// parse period
	cpuPeriod, err := fscommon.GetCgroupParamUint(filepath.Join(cgroupDir, "cpu.cfs_period_us"))
	if err != nil {
		l.Errorf("read cpu.cfs_period_us file error:%v, use default value", err)
		return defaultLimit
	}
	if cpuPeriod == 0 {
		l.Warn("cpu.cfs_period_us is 0, use default value")
		return defaultLimit
	}

	return float64(cpuQuota) / float64(cpuPeriod)
}

func GetCPUUsage(cgroupDir string) (totalUsage uint64, perCPUUsage []uint64, err error) {
	totalUsage, err = fscommon.GetCgroupParamUint(filepath.Join(cgroupDir, "cpuacct.usage"))
	if err != nil {
		return
	}
	perCPUUsage, err = getPerCPUUsage(cgroupDir)
	if err != nil {
		return
	}
	if totalUsage == 0 {
		l.Warn("get cpu total usage is 0, use per-cpu usage accumulation value")
		for _, usage := range perCPUUsage {
			totalUsage += usage
		}
	}
	return
}

func getPerCPUUsage(cgroupDir string) ([]uint64, error) {
	var perCPUUsage []uint64
	data, err := os.ReadFile(filepath.Join(cgroupDir, "cpuacct.usage_percpu"))
	if err != nil {
		return perCPUUsage, err
	}
	for _, value := range strings.Fields(string(data)) {
		value, err := strconv.ParseUint(value, 10, 64)
		if err != nil {
			return perCPUUsage, fmt.Errorf("unable to convert param value to uint64: %s", err)
		}
		perCPUUsage = append(perCPUUsage, value)
	}
	return perCPUUsage, nil
}