/
process_memory.go
118 lines (94 loc) · 3.52 KB
/
process_memory.go
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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
//go:build linux
// +build linux
package process
// ////////////////////////////////////////////////////////////////////////////////// //
// //
// Copyright (c) 2022 ESSENTIAL KAOS //
// Apache License, Version 2.0 <https://www.apache.org/licenses/LICENSE-2.0> //
// //
// ////////////////////////////////////////////////////////////////////////////////// //
import (
"bufio"
"errors"
"os"
"strconv"
"pkg.re/essentialkaos/ek.v12/strutil"
)
// ////////////////////////////////////////////////////////////////////////////////// //
// MemInfo contains process memory usage stats
type MemInfo struct {
VmPeak uint64 `json:"peak"` // Peak virtual memory size
VmSize uint64 `json:"size"` // Virtual memory size
VmLck uint64 `json:"lck"` // Locked memory size
VmPin uint64 `json:"pin"` // Pinned memory size (since Linux 3.2)
VmHWM uint64 `json:"hwm"` // Peak resident set size ("high water mark")
VmRSS uint64 `json:"rss"` // Resident set size
VmData uint64 `json:"data"` // Size of data
VmStk uint64 `json:"stk"` // Size of stack
VmExe uint64 `json:"exe"` // Size of text segments
VmLib uint64 `json:"lib"` // Shared library code size
VmPTE uint64 `json:"pte"` // Page table entries size (since Linux 2.6.10)
VmSwap uint64 `json:"swap"` // Swap size
}
// ////////////////////////////////////////////////////////////////////////////////// //
// codebeat:disable[LOC,ABC]
// GetMemInfo returns info about process memory usage
func GetMemInfo(pid int) (*MemInfo, error) {
fd, err := os.OpenFile(procFS+"/"+strconv.Itoa(pid)+"/status", os.O_RDONLY, 0)
if err != nil {
return nil, err
}
defer fd.Close()
r := bufio.NewReader(fd)
s := bufio.NewScanner(r)
info := &MemInfo{}
for s.Scan() {
text := s.Text()
if len(text) < 2 || text[:2] != "Vm" {
continue
}
switch strutil.ReadField(text, 0, true) {
case "VmPeak:":
info.VmPeak, err = parseSize(strutil.ReadField(text, 1, true))
case "VmSize:":
info.VmSize, err = parseSize(strutil.ReadField(text, 1, true))
case "VmLck:":
info.VmLck, err = parseSize(strutil.ReadField(text, 1, true))
case "VmPin:":
info.VmPin, err = parseSize(strutil.ReadField(text, 1, true))
case "VmHWM:":
info.VmHWM, err = parseSize(strutil.ReadField(text, 1, true))
case "VmRSS:":
info.VmRSS, err = parseSize(strutil.ReadField(text, 1, true))
case "VmData:":
info.VmData, err = parseSize(strutil.ReadField(text, 1, true))
case "VmStk:":
info.VmStk, err = parseSize(strutil.ReadField(text, 1, true))
case "VmExe:":
info.VmExe, err = parseSize(strutil.ReadField(text, 1, true))
case "VmLib:":
info.VmLib, err = parseSize(strutil.ReadField(text, 1, true))
case "VmPTE:":
info.VmPTE, err = parseSize(strutil.ReadField(text, 1, true))
case "VmSwap:":
info.VmSwap, err = parseSize(strutil.ReadField(text, 1, true))
}
if err != nil {
return nil, errors.New("Can't parse status file for given process")
}
}
if info.VmPeak+info.VmSize == 0 {
return nil, errors.New("Can't parse status file for given process")
}
return info, nil
}
// codebeat:enable[LOC,ABC]
// ////////////////////////////////////////////////////////////////////////////////// //
// parseSize parse size in kB
func parseSize(v string) (uint64, error) {
size, err := strconv.ParseUint(v, 10, 64)
if err != nil {
return 0, err
}
return size * 1024, nil
}