source: code/trunk/vendor/github.com/prometheus/procfs/proc_smaps.go@ 824

Last change on this file since 824 was 822, checked in by yakumo.izuru, 22 months ago

Prefer immortal.run over runit and rc.d, use vendored modules
for convenience.

Signed-off-by: Izuru Yakumo <yakumo.izuru@…>

File size: 3.9 KB
Line 
1// Copyright 2020 The Prometheus Authors
2// Licensed under the Apache License, Version 2.0 (the "License");
3// you may not use this file except in compliance with the License.
4// You may obtain a copy of the License at
5//
6// http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
14//go:build !windows
15// +build !windows
16
17package procfs
18
19import (
20 "bufio"
21 "errors"
22 "fmt"
23 "os"
24 "regexp"
25 "strconv"
26 "strings"
27
28 "github.com/prometheus/procfs/internal/util"
29)
30
31var (
32 // match the header line before each mapped zone in `/proc/pid/smaps`.
33 procSMapsHeaderLine = regexp.MustCompile(`^[a-f0-9].*$`)
34)
35
36type ProcSMapsRollup struct {
37 // Amount of the mapping that is currently resident in RAM.
38 Rss uint64
39 // Process's proportional share of this mapping.
40 Pss uint64
41 // Size in bytes of clean shared pages.
42 SharedClean uint64
43 // Size in bytes of dirty shared pages.
44 SharedDirty uint64
45 // Size in bytes of clean private pages.
46 PrivateClean uint64
47 // Size in bytes of dirty private pages.
48 PrivateDirty uint64
49 // Amount of memory currently marked as referenced or accessed.
50 Referenced uint64
51 // Amount of memory that does not belong to any file.
52 Anonymous uint64
53 // Amount would-be-anonymous memory currently on swap.
54 Swap uint64
55 // Process's proportional memory on swap.
56 SwapPss uint64
57}
58
59// ProcSMapsRollup reads from /proc/[pid]/smaps_rollup to get summed memory information of the
60// process.
61//
62// If smaps_rollup does not exists (require kernel >= 4.15), the content of /proc/pid/smaps will
63// we read and summed.
64func (p Proc) ProcSMapsRollup() (ProcSMapsRollup, error) {
65 data, err := util.ReadFileNoStat(p.path("smaps_rollup"))
66 if err != nil && os.IsNotExist(err) {
67 return p.procSMapsRollupManual()
68 }
69 if err != nil {
70 return ProcSMapsRollup{}, err
71 }
72
73 lines := strings.Split(string(data), "\n")
74 smaps := ProcSMapsRollup{}
75
76 // skip first line which don't contains information we need
77 lines = lines[1:]
78 for _, line := range lines {
79 if line == "" {
80 continue
81 }
82
83 if err := smaps.parseLine(line); err != nil {
84 return ProcSMapsRollup{}, err
85 }
86 }
87
88 return smaps, nil
89}
90
91// Read /proc/pid/smaps and do the roll-up in Go code.
92func (p Proc) procSMapsRollupManual() (ProcSMapsRollup, error) {
93 file, err := os.Open(p.path("smaps"))
94 if err != nil {
95 return ProcSMapsRollup{}, err
96 }
97 defer file.Close()
98
99 smaps := ProcSMapsRollup{}
100 scan := bufio.NewScanner(file)
101
102 for scan.Scan() {
103 line := scan.Text()
104
105 if procSMapsHeaderLine.MatchString(line) {
106 continue
107 }
108
109 if err := smaps.parseLine(line); err != nil {
110 return ProcSMapsRollup{}, err
111 }
112 }
113
114 return smaps, nil
115}
116
117func (s *ProcSMapsRollup) parseLine(line string) error {
118 kv := strings.SplitN(line, ":", 2)
119 if len(kv) != 2 {
120 fmt.Println(line)
121 return errors.New("invalid net/dev line, missing colon")
122 }
123
124 k := kv[0]
125 if k == "VmFlags" {
126 return nil
127 }
128
129 v := strings.TrimSpace(kv[1])
130 v = strings.TrimRight(v, " kB")
131
132 vKBytes, err := strconv.ParseUint(v, 10, 64)
133 if err != nil {
134 return err
135 }
136 vBytes := vKBytes * 1024
137
138 s.addValue(k, v, vKBytes, vBytes)
139
140 return nil
141}
142
143func (s *ProcSMapsRollup) addValue(k string, vString string, vUint uint64, vUintBytes uint64) {
144 switch k {
145 case "Rss":
146 s.Rss += vUintBytes
147 case "Pss":
148 s.Pss += vUintBytes
149 case "Shared_Clean":
150 s.SharedClean += vUintBytes
151 case "Shared_Dirty":
152 s.SharedDirty += vUintBytes
153 case "Private_Clean":
154 s.PrivateClean += vUintBytes
155 case "Private_Dirty":
156 s.PrivateDirty += vUintBytes
157 case "Referenced":
158 s.Referenced += vUintBytes
159 case "Anonymous":
160 s.Anonymous += vUintBytes
161 case "Swap":
162 s.Swap += vUintBytes
163 case "SwapPss":
164 s.SwapPss += vUintBytes
165 }
166}
Note: See TracBrowser for help on using the repository browser.