...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package sysfs
18
19 import (
20 "bufio"
21 "bytes"
22 "fmt"
23 "path/filepath"
24 "regexp"
25 "strconv"
26 "strings"
27
28 "github.com/prometheus/procfs/internal/util"
29 )
30
31 var (
32 nodePattern = "devices/system/node/node[0-9]*"
33 nodeNumberRegexp = regexp.MustCompile(`.*devices/system/node/node([0-9]*)`)
34 )
35
36 type VMStat struct {
37 NrFreePages uint64
38 NrZoneInactiveAnon uint64
39 NrZoneActiveAnon uint64
40 NrZoneInactiveFile uint64
41 NrZoneActiveFile uint64
42 NrZoneUnevictable uint64
43 NrZoneWritePending uint64
44 NrMlock uint64
45 NrPageTablePages uint64
46 NrKernelStack uint64
47 NrBounce uint64
48 NrZspages uint64
49 NrFreeCma uint64
50 NumaHit uint64
51 NumaMiss uint64
52 NumaForeign uint64
53 NumaInterleave uint64
54 NumaLocal uint64
55 NumaOther uint64
56 NrInactiveAnon uint64
57 NrActiveAnon uint64
58 NrInactiveFile uint64
59 NrActiveFile uint64
60 NrUnevictable uint64
61 NrSlabReclaimable uint64
62 NrSlabUnreclaimable uint64
63 NrIsolatedAnon uint64
64 NrIsolatedFile uint64
65 WorkingsetNodes uint64
66 WorkingsetRefault uint64
67 WorkingsetActivate uint64
68 WorkingsetRestore uint64
69 WorkingsetNodereclaim uint64
70 NrAnonPages uint64
71 NrMapped uint64
72 NrFilePages uint64
73 NrDirty uint64
74 NrWriteback uint64
75 NrWritebackTemp uint64
76 NrShmem uint64
77 NrShmemHugepages uint64
78 NrShmemPmdmapped uint64
79 NrFileHugepages uint64
80 NrFilePmdmapped uint64
81 NrAnonTransparentHugepages uint64
82 NrVmscanWrite uint64
83 NrVmscanImmediateReclaim uint64
84 NrDirtied uint64
85 NrWritten uint64
86 NrKernelMiscReclaimable uint64
87 NrFollPinAcquired uint64
88 NrFollPinReleased uint64
89 }
90
91 func (fs FS) VMStatNUMA() (map[int]VMStat, error) {
92 m := make(map[int]VMStat)
93 nodes, err := filepath.Glob(fs.sys.Path(nodePattern))
94 if err != nil {
95 return nil, err
96 }
97
98 for _, node := range nodes {
99 nodeNumbers := nodeNumberRegexp.FindStringSubmatch(node)
100 if len(nodeNumbers) != 2 {
101 continue
102 }
103 nodeNumber, err := strconv.Atoi(nodeNumbers[1])
104 if err != nil {
105 return nil, err
106 }
107 file, err := util.ReadFileNoStat(filepath.Join(node, "vmstat"))
108 if err != nil {
109 return nil, err
110 }
111 nodeStats, err := parseVMStatNUMA(file)
112 if err != nil {
113 return nil, err
114 }
115 m[nodeNumber] = nodeStats
116 }
117 return m, nil
118 }
119
120 func parseVMStatNUMA(r []byte) (VMStat, error) {
121 var (
122 vmStat = VMStat{}
123 scanner = bufio.NewScanner(bytes.NewReader(r))
124 )
125
126 for scanner.Scan() {
127 line := strings.TrimSpace(scanner.Text())
128 if line == "" {
129 continue
130 }
131 parts := strings.Fields(line)
132 if len(parts) != 2 {
133 return vmStat, fmt.Errorf("line scan did not return 2 fields: %s", line)
134 }
135
136 fv, err := strconv.ParseUint(parts[1], 10, 64)
137 if err != nil {
138 return vmStat, fmt.Errorf("invalid value in vmstat: %w", err)
139 }
140 switch parts[0] {
141 case "nr_free_pages":
142 vmStat.NrFreePages = fv
143 case "nr_zone_inactive_anon":
144 vmStat.NrZoneInactiveAnon = fv
145 case "nr_zone_active_anon":
146 vmStat.NrZoneActiveAnon = fv
147 case "nr_zone_inactive_file":
148 vmStat.NrZoneInactiveFile = fv
149 case "nr_zone_active_file":
150 vmStat.NrZoneActiveFile = fv
151 case "nr_zone_unevictable":
152 vmStat.NrZoneUnevictable = fv
153 case "nr_zone_write_pending":
154 vmStat.NrZoneWritePending = fv
155 case "nr_mlock":
156 vmStat.NrMlock = fv
157 case "nr_page_table_pages":
158 vmStat.NrPageTablePages = fv
159 case "nr_kernel_stack":
160 vmStat.NrKernelStack = fv
161 case "nr_bounce":
162 vmStat.NrBounce = fv
163 case "nr_zspages":
164 vmStat.NrZspages = fv
165 case "nr_free_cma":
166 vmStat.NrFreeCma = fv
167 case "numa_hit":
168 vmStat.NumaHit = fv
169 case "numa_miss":
170 vmStat.NumaMiss = fv
171 case "numa_foreign":
172 vmStat.NumaForeign = fv
173 case "numa_interleave":
174 vmStat.NumaInterleave = fv
175 case "numa_local":
176 vmStat.NumaLocal = fv
177 case "numa_other":
178 vmStat.NumaOther = fv
179 case "nr_inactive_anon":
180 vmStat.NrInactiveAnon = fv
181 case "nr_active_anon":
182 vmStat.NrActiveAnon = fv
183 case "nr_inactive_file":
184 vmStat.NrInactiveFile = fv
185 case "nr_active_file":
186 vmStat.NrActiveFile = fv
187 case "nr_unevictable":
188 vmStat.NrUnevictable = fv
189 case "nr_slab_reclaimable":
190 vmStat.NrSlabReclaimable = fv
191 case "nr_slab_unreclaimable":
192 vmStat.NrSlabUnreclaimable = fv
193 case "nr_isolated_anon":
194 vmStat.NrIsolatedAnon = fv
195 case "nr_isolated_file":
196 vmStat.NrIsolatedFile = fv
197 case "workingset_nodes":
198 vmStat.WorkingsetNodes = fv
199 case "workingset_refault":
200 vmStat.WorkingsetRefault = fv
201 case "workingset_activate":
202 vmStat.WorkingsetActivate = fv
203 case "workingset_restore":
204 vmStat.WorkingsetRestore = fv
205 case "workingset_nodereclaim":
206 vmStat.WorkingsetNodereclaim = fv
207 case "nr_anon_pages":
208 vmStat.NrAnonPages = fv
209 case "nr_mapped":
210 vmStat.NrMapped = fv
211 case "nr_file_pages":
212 vmStat.NrFilePages = fv
213 case "nr_dirty":
214 vmStat.NrDirty = fv
215 case "nr_writeback":
216 vmStat.NrWriteback = fv
217 case "nr_writeback_temp":
218 vmStat.NrWritebackTemp = fv
219 case "nr_shmem":
220 vmStat.NrShmem = fv
221 case "nr_shmem_hugepages":
222 vmStat.NrShmemHugepages = fv
223 case "nr_shmem_pmdmapped":
224 vmStat.NrShmemPmdmapped = fv
225 case "nr_file_hugepages":
226 vmStat.NrFileHugepages = fv
227 case "nr_file_pmdmapped":
228 vmStat.NrFilePmdmapped = fv
229 case "nr_anon_transparent_hugepages":
230 vmStat.NrAnonTransparentHugepages = fv
231 case "nr_vmscan_write":
232 vmStat.NrVmscanWrite = fv
233 case "nr_vmscan_immediate_reclaim":
234 vmStat.NrVmscanImmediateReclaim = fv
235 case "nr_dirtied":
236 vmStat.NrDirtied = fv
237 case "nr_written":
238 vmStat.NrWritten = fv
239 case "nr_kernel_misc_reclaimable":
240 vmStat.NrKernelMiscReclaimable = fv
241 case "nr_foll_pin_acquired":
242 vmStat.NrFollPinAcquired = fv
243 case "nr_foll_pin_released":
244 vmStat.NrFollPinReleased = fv
245 }
246
247 }
248 return vmStat, scanner.Err()
249 }
250
View as plain text