cpu.go 1.94 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
package fs2

import (
	"bufio"
	"os"
	"path/filepath"
	"strings"

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

func GetCPULimit(cgroupDir string, defaultLimit float64) float64 {
	contents, err := fscommon.GetCgroupParamString(filepath.Join(cgroupDir, "cpu.max"))
	if err != nil {
		l.Errorf("read cpu.max file error:%v, use default value", err)
		return defaultLimit
	}
	fields := strings.Split(contents, " ")
	if len(fields) != 2 {
		l.Errorf("parse cpu.max file error, contents:%s, use default value", contents)
		return defaultLimit
	}

	// parse quota
	if fields[0] == "max" {
		l.Warn("cpu.max quota is max, use default value")
		return defaultLimit
	}
	cpuQuota, err := fscommon.ParseUint(fields[0], 10, 64)
	if err != nil {
		l.Errorf("parse cpu.max quota error:%v, contents:%s, use default value", err, fields[0])
		return defaultLimit
	}
	if cpuQuota == 0 {
		l.Warn("cpu.max quota is 0, use default value")
		return defaultLimit
	}

	// parse period
	cpuPeriod, err := fscommon.ParseUint(fields[1], 10, 64)
	if err != nil {
		l.Errorf("parse cpu.max period error:%v, contents:%s, use default value", err, fields[1])
		return defaultLimit
	}
	if cpuPeriod == 0 {
		l.Warn("cpu.max period is 0, use default value")
		return defaultLimit
	}

	return float64(cpuQuota) / float64(cpuPeriod)
}

func GetCPUUsage(cgroupDir string) (totalUsage uint64, err error) {
	return statCPU(cgroupDir)
}

// Copied from: https://github.com/opencontainers/runc/blob/main/libcontainer/cgroups/fs2/cpu.go
func statCPU(dirPath string) (cpuUsage uint64, err error) {
	f, err := os.Open(filepath.Join(dirPath, "cpu.stat"))
	if err != nil {
		return cpuUsage, err
	}
	defer f.Close()

	sc := bufio.NewScanner(f)
	for sc.Scan() {
		t, v, err := fscommon.ParseKeyValue(sc.Text())
		if err != nil {
			return cpuUsage, err
		}
		switch t {
		case "usage_usec":
			return v * 1000, nil
		}
	}
	if err := sc.Err(); err != nil {
		return cpuUsage, err
	}
	return cpuUsage, nil
}