memory.go 2.26 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
90
91
92
93
94
95
96
97
package fs

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

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

var (
	defaultMem = "9223372036854771712"
)

func MemorySubSystemName() string {
	return "memory"
}

func GetMemoryLimit(cgroupDir string, defaultLimit float64) float64 {
	contents, err := fscommon.GetCgroupParamString(filepath.Join(cgroupDir, "memory.limit_in_bytes"))
	if err != nil {
		l.Errorf("read memory.limit_in_bytes error:%v, use default value", err)
		return defaultLimit
	}
	if contents == defaultMem {
		l.Warn("memory.limit_in_bytes is defaultMem, use default value")
		return defaultLimit
	}

	memLimit, err := fscommon.ParseUint(contents, 10, 64)
	if err != nil {
		l.Errorf("parse memory.limit_in_bytes error:%v, contents:%s, use default value", err, contents)
		return defaultLimit
	}
	if memLimit == 0 {
		l.Warn("memory.limit_in_bytes is 0, use default value")
		return defaultLimit
	}

	return float64(memLimit)
}

func GetMemoryUsage(cgroupDir string) (usage uint64, workingSet uint64, err error) {
	var stats map[string]uint64
	stats, err = ParseMemoryStat(filepath.Join(cgroupDir, "memory.stat"))
	if err != nil {
		return
	}

	usage, err = fscommon.GetCgroupParamUint(filepath.Join(cgroupDir, "memory.usage_in_bytes"))
	if err != nil {
		return
	}

	workingSet = usage
	if v, ok := stats["total_inactive_file"]; ok {
		if workingSet < v {
			workingSet = 0
		} else {
			workingSet -= v
		}
	}

	return
}

func ParseMemoryStat(statPath string) (map[string]uint64, error) {
	statFile, err := os.Open(statPath)
	if err != nil {
		return nil, err
	}
	defer statFile.Close()

	stats := make(map[string]uint64)
	sc := bufio.NewScanner(statFile)
	for sc.Scan() {
		t, v, err := fscommon.ParseKeyValue(sc.Text())
		if err != nil {
			return nil, err
		}
		stats[t] = v
	}
	if err = sc.Err(); err != nil {
		return nil, err
	}

	return stats, nil
}

func GetKernelMemoryUsage(cgroupDir string) (usage uint64, err error) {
	return fscommon.GetCgroupParamUint(filepath.Join(cgroupDir, "memory.kmem.usage_in_bytes"))
}

func GetKernelMemorySlabInfo(cgroupDir string) (slabInfo SlabInfo, err error) {
	return ParseSlabInfo(filepath.Join(cgroupDir, "memory.kmem.slabinfo"))
}