master
c 757 lines 34.8 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 #include "plugin_proc.h"
4
5 #define PLUGIN_PROC_MODULE_VMSTAT_NAME "/proc/vmstat"
6
7 #define OOM_KILL_STRING "oom_kill"
8
9 #define _COMMON_PLUGIN_NAME PLUGIN_PROC_NAME
10 #define _COMMON_PLUGIN_MODULE_NAME PLUGIN_PROC_MODULE_VMSTAT_NAME
11 #include "../common-contexts/common-contexts.h"
12
13
14 int do_proc_vmstat(int update_every, usec_t dt) {
15 (void)dt;
16
17 static procfile *ff = NULL;
18 static int do_swapio = -1, do_io = -1, do_pgfaults = -1, do_oom_kill = -1, do_numa = -1, do_thp = -1, do_zswapio = -1, do_balloon = -1, do_ksm = -1;
19 static int has_numa = -1;
20
21 static ARL_BASE *arl_base = NULL;
22 static unsigned long long numa_foreign = 0ULL;
23 static unsigned long long numa_hint_faults = 0ULL;
24 static unsigned long long numa_hint_faults_local = 0ULL;
25 static unsigned long long numa_huge_pte_updates = 0ULL;
26 static unsigned long long numa_interleave = 0ULL;
27 static unsigned long long numa_local = 0ULL;
28 static unsigned long long numa_other = 0ULL;
29 static unsigned long long numa_pages_migrated = 0ULL;
30 static unsigned long long numa_pte_updates = 0ULL;
31 static unsigned long long pgfault = 0ULL;
32 static unsigned long long pgmajfault = 0ULL;
33 static unsigned long long pgpgin = 0ULL;
34 static unsigned long long pgpgout = 0ULL;
35 static unsigned long long pswpin = 0ULL;
36 static unsigned long long pswpout = 0ULL;
37 static unsigned long long oom_kill = 0ULL;
38
39 // THP page migration
40 // static unsigned long long pgmigrate_success = 0ULL;
41 // static unsigned long long pgmigrate_fail = 0ULL;
42 // static unsigned long long thp_migration_success = 0ULL;
43 // static unsigned long long thp_migration_fail = 0ULL;
44 // static unsigned long long thp_migration_split = 0ULL;
45
46 // Compaction cost model
47 // https://lore.kernel.org/lkml/20121022080525.GB2198@suse.de/
48 // static unsigned long long compact_migrate_scanned = 0ULL;
49 // static unsigned long long compact_free_scanned = 0ULL;
50 // static unsigned long long compact_isolated = 0ULL;
51
52 // THP defragmentation
53 static unsigned long long compact_stall = 0ULL; // incremented when an application stalls allocating THP
54 static unsigned long long compact_fail = 0ULL; // defragmentation events that failed
55 static unsigned long long compact_success = 0ULL; // defragmentation events that succeeded
56
57 // ?
58 // static unsigned long long compact_daemon_wake = 0ULL;
59 // static unsigned long long compact_daemon_migrate_scanned = 0ULL;
60 // static unsigned long long compact_daemon_free_scanned = 0ULL;
61
62 // ?
63 // static unsigned long long htlb_buddy_alloc_success = 0ULL;
64 // static unsigned long long htlb_buddy_alloc_fail = 0ULL;
65
66 // ?
67 // static unsigned long long cma_alloc_success = 0ULL;
68 // static unsigned long long cma_alloc_fail = 0ULL;
69
70 // ?
71 // static unsigned long long unevictable_pgs_culled = 0ULL;
72 // static unsigned long long unevictable_pgs_scanned = 0ULL;
73 // static unsigned long long unevictable_pgs_rescued = 0ULL;
74 // static unsigned long long unevictable_pgs_mlocked = 0ULL;
75 // static unsigned long long unevictable_pgs_munlocked = 0ULL;
76 // static unsigned long long unevictable_pgs_cleared = 0ULL;
77 // static unsigned long long unevictable_pgs_stranded = 0ULL;
78
79 // THP handling of page faults
80 static unsigned long long thp_fault_alloc = 0ULL; // is incremented every time a huge page is successfully allocated to handle a page fault. This applies to both the first time a page is faulted and for COW faults.
81 static unsigned long long thp_fault_fallback = 0ULL; // is incremented if a page fault fails to allocate a huge page and instead falls back to using small pages.
82 static unsigned long long thp_fault_fallback_charge = 0ULL; // is incremented if a page fault fails to charge a huge page and instead falls back to using small pages even though the allocation was successful.
83
84 // khugepaged collapsing of small pages into huge pages
85 static unsigned long long thp_collapse_alloc = 0ULL; // is incremented by khugepaged when it has found a range of pages to collapse into one huge page and has successfully allocated a new huge page to store the data.
86 static unsigned long long thp_collapse_alloc_failed = 0ULL; // is incremented if khugepaged found a range of pages that should be collapsed into one huge page but failed the allocation.
87
88 // THP handling of file allocations
89 static unsigned long long thp_file_alloc = 0ULL; // is incremented every time a file huge page is successfully allocated
90 static unsigned long long thp_file_fallback = 0ULL; // is incremented if a file huge page is attempted to be allocated but fails and instead falls back to using small pages
91 static unsigned long long thp_file_fallback_charge = 0ULL; // is incremented if a file huge page cannot be charged and instead falls back to using small pages even though the allocation was successful
92 static unsigned long long thp_file_mapped = 0ULL; // is incremented every time a file huge page is mapped into user address space
93
94 // THP splitting of huge pages into small pages
95 static unsigned long long thp_split_page = 0ULL;
96 static unsigned long long thp_split_page_failed = 0ULL;
97 static unsigned long long thp_deferred_split_page = 0ULL; // is incremented when a huge page is put onto split queue. This happens when a huge page is partially unmapped and splitting it would free up some memory. Pages on split queue are going to be split under memory pressure
98 static unsigned long long thp_split_pmd = 0ULL; // is incremented every time a PMD split into table of PTEs. This can happen, for instance, when application calls mprotect() or munmap() on part of huge page. It doesn’t split huge page, only page table entry
99
100 // ?
101 // static unsigned long long thp_scan_exceed_none_pte = 0ULL;
102 // static unsigned long long thp_scan_exceed_swap_pte = 0ULL;
103 // static unsigned long long thp_scan_exceed_share_pte = 0ULL;
104 // static unsigned long long thp_split_pud = 0ULL;
105
106 // THP Zero Huge Page
107 static unsigned long long thp_zero_page_alloc = 0ULL; // is incremented every time a huge zero page used for thp is successfully allocated. Note, it doesn’t count every map of the huge zero page, only its allocation
108 static unsigned long long thp_zero_page_alloc_failed = 0ULL; // is incremented if kernel fails to allocate huge zero page and falls back to using small pages
109
110 // THP Swap Out
111 static unsigned long long thp_swpout = 0ULL; // is incremented every time a huge page is swapout in one piece without splitting
112 static unsigned long long thp_swpout_fallback = 0ULL; // is incremented if a huge page has to be split before swapout. Usually because failed to allocate some continuous swap space for the huge page
113
114 // memory ballooning
115 // Current size of balloon is (balloon_inflate - balloon_deflate) pages
116 static unsigned long long balloon_inflate = 0ULL;
117 static unsigned long long balloon_deflate = 0ULL;
118 static unsigned long long balloon_migrate = 0ULL;
119
120 // ?
121 // static unsigned long long swap_ra = 0ULL;
122 // static unsigned long long swap_ra_hit = 0ULL;
123
124 static unsigned long long ksm_swpin_copy = 0ULL; // is incremented every time a KSM page is copied when swapping in
125 static unsigned long long cow_ksm = 0ULL; // is incremented every time a KSM page triggers copy on write (COW) when users try to write to a KSM page, we have to make a copy
126
127 // zswap
128 static unsigned long long zswpin = 0ULL;
129 static unsigned long long zswpout = 0ULL;
130
131 // ?
132 // static unsigned long long direct_map_level2_splits = 0ULL;
133 // static unsigned long long direct_map_level3_splits = 0ULL;
134 // static unsigned long long nr_unstable = 0ULL;
135
136 if(unlikely(!ff)) {
137 char filename[FILENAME_MAX + 1];
138 snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/proc/vmstat");
139 ff = procfile_open(inicfg_get(&netdata_config, "plugin:proc:/proc/vmstat", "filename to monitor", filename), " \t:", PROCFILE_FLAG_DEFAULT);
140 if(unlikely(!ff)) return 1;
141 }
142
143 ff = procfile_readall(ff);
144 if(unlikely(!ff)) return 0; // we return 0, so that we will retry to open it next time
145
146 size_t lines = procfile_lines(ff), l;
147
148 if(unlikely(!arl_base)) {
149 do_swapio = inicfg_get_boolean_ondemand(&netdata_config, "plugin:proc:/proc/vmstat", "swap i/o", CONFIG_BOOLEAN_AUTO);
150 do_io = inicfg_get_boolean(&netdata_config, "plugin:proc:/proc/vmstat", "disk i/o", CONFIG_BOOLEAN_YES);
151 do_pgfaults = inicfg_get_boolean(&netdata_config, "plugin:proc:/proc/vmstat", "memory page faults", CONFIG_BOOLEAN_YES);
152 do_oom_kill = inicfg_get_boolean(&netdata_config, "plugin:proc:/proc/vmstat", "out of memory kills", CONFIG_BOOLEAN_AUTO);
153 do_numa = inicfg_get_boolean_ondemand(&netdata_config, "plugin:proc:/proc/vmstat", "system-wide numa metric summary", CONFIG_BOOLEAN_AUTO);
154 do_thp = inicfg_get_boolean_ondemand(&netdata_config, "plugin:proc:/proc/vmstat", "transparent huge pages", CONFIG_BOOLEAN_AUTO);
155 do_zswapio = inicfg_get_boolean_ondemand(&netdata_config, "plugin:proc:/proc/vmstat", "zswap i/o", CONFIG_BOOLEAN_AUTO);
156 do_balloon = inicfg_get_boolean_ondemand(&netdata_config, "plugin:proc:/proc/vmstat", "memory ballooning", CONFIG_BOOLEAN_AUTO);
157 do_ksm = inicfg_get_boolean_ondemand(&netdata_config, "plugin:proc:/proc/vmstat", "kernel same memory", CONFIG_BOOLEAN_AUTO);
158
159 arl_base = arl_create("vmstat", NULL, 60);
160 arl_expect(arl_base, "pgfault", &pgfault);
161 arl_expect(arl_base, "pgmajfault", &pgmajfault);
162 arl_expect(arl_base, "pgpgin", &pgpgin);
163 arl_expect(arl_base, "pgpgout", &pgpgout);
164 arl_expect(arl_base, "pswpin", &pswpin);
165 arl_expect(arl_base, "pswpout", &pswpout);
166
167 int has_oom_kill = 0;
168
169 for (l = 0; l < lines; l++) {
170 if (!strcmp(procfile_lineword(ff, l, 0), OOM_KILL_STRING)) {
171 has_oom_kill = 1;
172 break;
173 }
174 }
175
176 if (has_oom_kill)
177 arl_expect(arl_base, OOM_KILL_STRING, &oom_kill);
178 else
179 do_oom_kill = CONFIG_BOOLEAN_NO;
180
181 if (do_numa == CONFIG_BOOLEAN_YES || (do_numa == CONFIG_BOOLEAN_AUTO && get_numa_node_count() >= 2)) {
182 arl_expect(arl_base, "numa_foreign", &numa_foreign);
183 arl_expect(arl_base, "numa_hint_faults_local", &numa_hint_faults_local);
184 arl_expect(arl_base, "numa_hint_faults", &numa_hint_faults);
185 arl_expect(arl_base, "numa_huge_pte_updates", &numa_huge_pte_updates);
186 arl_expect(arl_base, "numa_interleave", &numa_interleave);
187 arl_expect(arl_base, "numa_local", &numa_local);
188 arl_expect(arl_base, "numa_other", &numa_other);
189 arl_expect(arl_base, "numa_pages_migrated", &numa_pages_migrated);
190 arl_expect(arl_base, "numa_pte_updates", &numa_pte_updates);
191 } else {
192 // Do not expect numa metrics when they are not needed.
193 // By not adding them, the ARL will stop processing the file
194 // when all the expected metrics are collected.
195 // Also ARL will not parse their values.
196 has_numa = 0;
197 do_numa = CONFIG_BOOLEAN_NO;
198 }
199
200 if(do_thp == CONFIG_BOOLEAN_YES || do_thp == CONFIG_BOOLEAN_AUTO) {
201 // arl_expect(arl_base, "pgmigrate_success", &pgmigrate_success);
202 // arl_expect(arl_base, "pgmigrate_fail", &pgmigrate_fail);
203 // arl_expect(arl_base, "thp_migration_success", &thp_migration_success);
204 // arl_expect(arl_base, "thp_migration_fail", &thp_migration_fail);
205 // arl_expect(arl_base, "thp_migration_split", &thp_migration_split);
206 // arl_expect(arl_base, "compact_migrate_scanned", &compact_migrate_scanned);
207 // arl_expect(arl_base, "compact_free_scanned", &compact_free_scanned);
208 // arl_expect(arl_base, "compact_isolated", &compact_isolated);
209 arl_expect(arl_base, "compact_stall", &compact_stall);
210 arl_expect(arl_base, "compact_fail", &compact_fail);
211 arl_expect(arl_base, "compact_success", &compact_success);
212 // arl_expect(arl_base, "compact_daemon_wake", &compact_daemon_wake);
213 // arl_expect(arl_base, "compact_daemon_migrate_scanned", &compact_daemon_migrate_scanned);
214 // arl_expect(arl_base, "compact_daemon_free_scanned", &compact_daemon_free_scanned);
215 arl_expect(arl_base, "thp_fault_alloc", &thp_fault_alloc);
216 arl_expect(arl_base, "thp_fault_fallback", &thp_fault_fallback);
217 arl_expect(arl_base, "thp_fault_fallback_charge", &thp_fault_fallback_charge);
218 arl_expect(arl_base, "thp_collapse_alloc", &thp_collapse_alloc);
219 arl_expect(arl_base, "thp_collapse_alloc_failed", &thp_collapse_alloc_failed);
220 arl_expect(arl_base, "thp_file_alloc", &thp_file_alloc);
221 arl_expect(arl_base, "thp_file_fallback", &thp_file_fallback);
222 arl_expect(arl_base, "thp_file_fallback_charge", &thp_file_fallback_charge);
223 arl_expect(arl_base, "thp_file_mapped", &thp_file_mapped);
224 arl_expect(arl_base, "thp_split_page", &thp_split_page);
225 arl_expect(arl_base, "thp_split_page_failed", &thp_split_page_failed);
226 arl_expect(arl_base, "thp_deferred_split_page", &thp_deferred_split_page);
227 arl_expect(arl_base, "thp_split_pmd", &thp_split_pmd);
228 arl_expect(arl_base, "thp_zero_page_alloc", &thp_zero_page_alloc);
229 arl_expect(arl_base, "thp_zero_page_alloc_failed", &thp_zero_page_alloc_failed);
230 arl_expect(arl_base, "thp_swpout", &thp_swpout);
231 arl_expect(arl_base, "thp_swpout_fallback", &thp_swpout_fallback);
232 }
233
234 if(do_balloon == CONFIG_BOOLEAN_YES || do_balloon == CONFIG_BOOLEAN_AUTO) {
235 arl_expect(arl_base, "balloon_inflate", &balloon_inflate);
236 arl_expect(arl_base, "balloon_deflate", &balloon_deflate);
237 arl_expect(arl_base, "balloon_migrate", &balloon_migrate);
238 }
239
240 if(do_ksm == CONFIG_BOOLEAN_YES || do_ksm == CONFIG_BOOLEAN_AUTO) {
241 arl_expect(arl_base, "ksm_swpin_copy", &ksm_swpin_copy);
242 arl_expect(arl_base, "cow_ksm", &cow_ksm);
243 }
244
245 if(do_zswapio == CONFIG_BOOLEAN_YES || do_zswapio == CONFIG_BOOLEAN_AUTO) {
246 arl_expect(arl_base, "zswpin", &zswpin);
247 arl_expect(arl_base, "zswpout", &zswpout);
248 }
249 }
250
251 arl_begin(arl_base);
252 for(l = 0; l < lines ;l++) {
253 size_t words = procfile_linewords(ff, l);
254 if(unlikely(words < 2)) {
255 if(unlikely(words)) collector_error("Cannot read /proc/vmstat line %zu. Expected 2 params, read %zu.", l, words);
256 continue;
257 }
258
259 if(unlikely(arl_check(arl_base,
260 procfile_lineword(ff, l, 0),
261 procfile_lineword(ff, l, 1)))) break;
262 }
263
264 // --------------------------------------------------------------------
265
266 if (is_mem_swap_enabled && (do_swapio == CONFIG_BOOLEAN_YES || do_swapio == CONFIG_BOOLEAN_AUTO)) {
267 do_swapio = CONFIG_BOOLEAN_YES;
268
269 static RRDSET *st_swapio = NULL;
270 static RRDDIM *rd_in = NULL, *rd_out = NULL;
271
272 if(unlikely(!st_swapio)) {
273 st_swapio = rrdset_create_localhost(
274 "mem"
275 , "swapio"
276 , NULL
277 , "swap"
278 , NULL
279 , "Swap I/O"
280 , "KiB/s"
281 , PLUGIN_PROC_NAME
282 , PLUGIN_PROC_MODULE_VMSTAT_NAME
283 , NETDATA_CHART_PRIO_MEM_SWAPIO
284 , update_every
285 , RRDSET_TYPE_AREA
286 );
287
288 rd_in = rrddim_add(st_swapio, "in", NULL, sysconf(_SC_PAGESIZE), 1024, RRD_ALGORITHM_INCREMENTAL);
289 rd_out = rrddim_add(st_swapio, "out", NULL, -sysconf(_SC_PAGESIZE), 1024, RRD_ALGORITHM_INCREMENTAL);
290 }
291
292 rrddim_set_by_pointer(st_swapio, rd_in, pswpin);
293 rrddim_set_by_pointer(st_swapio, rd_out, pswpout);
294 rrdset_done(st_swapio);
295 }
296
297 // --------------------------------------------------------------------
298
299 if(do_io) {
300 static RRDSET *st_io = NULL;
301 static RRDDIM *rd_in = NULL, *rd_out = NULL;
302
303 if(unlikely(!st_io)) {
304 st_io = rrdset_create_localhost(
305 "system"
306 , "pgpgio"
307 , NULL
308 , "disk"
309 , NULL
310 , "Memory Paged from/to disk"
311 , "KiB/s"
312 , PLUGIN_PROC_NAME
313 , PLUGIN_PROC_MODULE_VMSTAT_NAME
314 , NETDATA_CHART_PRIO_SYSTEM_PGPGIO
315 , update_every
316 , RRDSET_TYPE_AREA
317 );
318
319 rd_in = rrddim_add(st_io, "in", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
320 rd_out = rrddim_add(st_io, "out", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
321 }
322
323 rrddim_set_by_pointer(st_io, rd_in, pgpgin);
324 rrddim_set_by_pointer(st_io, rd_out, pgpgout);
325 rrdset_done(st_io);
326 }
327
328 // --------------------------------------------------------------------
329
330 if(do_pgfaults) {
331 common_mem_pgfaults(pgfault, pgmajfault, update_every);
332 }
333
334 // --------------------------------------------------------------------
335
336 if (do_oom_kill == CONFIG_BOOLEAN_YES || do_oom_kill == CONFIG_BOOLEAN_AUTO) {
337 static RRDSET *st_oom_kill = NULL;
338 static RRDDIM *rd_oom_kill = NULL;
339
340 do_oom_kill = CONFIG_BOOLEAN_YES;
341
342 if(unlikely(!st_oom_kill)) {
343 st_oom_kill = rrdset_create_localhost(
344 "mem"
345 , "oom_kill"
346 , NULL
347 , "OOM kills"
348 , NULL
349 , "Out of Memory Kills"
350 , "kills/s"
351 , PLUGIN_PROC_NAME
352 , PLUGIN_PROC_MODULE_VMSTAT_NAME
353 , NETDATA_CHART_PRIO_MEM_SYSTEM_OOM_KILL
354 , update_every
355 , RRDSET_TYPE_LINE
356 );
357
358 rd_oom_kill = rrddim_add(st_oom_kill, "kills", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
359 }
360
361 rrddim_set_by_pointer(st_oom_kill, rd_oom_kill, oom_kill);
362 rrdset_done(st_oom_kill);
363 }
364
365 // --------------------------------------------------------------------
366
367 // Ondemand criteria for NUMA. Since this won't change at run time, we
368 // check it only once. We check whether the node count is >= 2 because
369 // single-node systems have uninteresting statistics (since all accesses
370 // are local).
371 if(unlikely(has_numa == -1))
372
373 has_numa = (numa_local || numa_foreign || numa_interleave || numa_other || numa_pte_updates ||
374 numa_huge_pte_updates || numa_hint_faults || numa_hint_faults_local || numa_pages_migrated) ? 1 : 0;
375
376 if(do_numa == CONFIG_BOOLEAN_YES || (do_numa == CONFIG_BOOLEAN_AUTO && has_numa)) {
377 do_numa = CONFIG_BOOLEAN_YES;
378
379 static RRDSET *st_numa = NULL;
380 static RRDDIM *rd_local = NULL, *rd_foreign = NULL, *rd_interleave = NULL, *rd_other = NULL, *rd_pte_updates = NULL, *rd_huge_pte_updates = NULL, *rd_hint_faults = NULL, *rd_hint_faults_local = NULL, *rd_pages_migrated = NULL;
381
382 if(unlikely(!st_numa)) {
383 st_numa = rrdset_create_localhost(
384 "mem"
385 , "numa"
386 , NULL
387 , "numa"
388 , NULL
389 , "NUMA events"
390 , "events/s"
391 , PLUGIN_PROC_NAME
392 , PLUGIN_PROC_MODULE_VMSTAT_NAME
393 , NETDATA_CHART_PRIO_MEM_NUMA
394 , update_every
395 , RRDSET_TYPE_LINE
396 );
397
398 // These depend on CONFIG_NUMA in the kernel.
399 rd_local = rrddim_add(st_numa, "local", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
400 rd_foreign = rrddim_add(st_numa, "foreign", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
401 rd_interleave = rrddim_add(st_numa, "interleave", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
402 rd_other = rrddim_add(st_numa, "other", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
403
404 // The following stats depend on CONFIG_NUMA_BALANCING in the
405 // kernel.
406 rd_pte_updates = rrddim_add(st_numa, "pte_updates", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
407 rd_huge_pte_updates = rrddim_add(st_numa, "huge_pte_updates", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
408 rd_hint_faults = rrddim_add(st_numa, "hint_faults", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
409 rd_hint_faults_local = rrddim_add(st_numa, "hint_faults_local", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
410 rd_pages_migrated = rrddim_add(st_numa, "pages_migrated", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
411 }
412
413 rrddim_set_by_pointer(st_numa, rd_local, numa_local);
414 rrddim_set_by_pointer(st_numa, rd_foreign, numa_foreign);
415 rrddim_set_by_pointer(st_numa, rd_interleave, numa_interleave);
416 rrddim_set_by_pointer(st_numa, rd_other, numa_other);
417
418 rrddim_set_by_pointer(st_numa, rd_pte_updates, numa_pte_updates);
419 rrddim_set_by_pointer(st_numa, rd_huge_pte_updates, numa_huge_pte_updates);
420 rrddim_set_by_pointer(st_numa, rd_hint_faults, numa_hint_faults);
421 rrddim_set_by_pointer(st_numa, rd_hint_faults_local, numa_hint_faults_local);
422 rrddim_set_by_pointer(st_numa, rd_pages_migrated, numa_pages_migrated);
423
424 rrdset_done(st_numa);
425 }
426
427 // --------------------------------------------------------------------
428
429 if (do_balloon == CONFIG_BOOLEAN_YES || do_balloon == CONFIG_BOOLEAN_AUTO) {
430 do_balloon = CONFIG_BOOLEAN_YES;
431
432 static RRDSET *st_balloon = NULL;
433 static RRDDIM *rd_inflate = NULL, *rd_deflate = NULL, *rd_migrate = NULL;
434
435 if(unlikely(!st_balloon)) {
436 st_balloon = rrdset_create_localhost(
437 "mem"
438 , "balloon"
439 , NULL
440 , "balloon"
441 , NULL
442 , "Memory Ballooning Operations"
443 , "KiB/s"
444 , PLUGIN_PROC_NAME
445 , PLUGIN_PROC_MODULE_VMSTAT_NAME
446 , NETDATA_CHART_PRIO_MEM_BALLOON
447 , update_every
448 , RRDSET_TYPE_LINE
449 );
450
451 rd_inflate = rrddim_add(st_balloon, "inflate", NULL, sysconf(_SC_PAGESIZE), 1024, RRD_ALGORITHM_INCREMENTAL);
452 rd_deflate = rrddim_add(st_balloon, "deflate", NULL, -sysconf(_SC_PAGESIZE), 1024, RRD_ALGORITHM_INCREMENTAL);
453 rd_migrate = rrddim_add(st_balloon, "migrate", NULL, sysconf(_SC_PAGESIZE), 1024, RRD_ALGORITHM_INCREMENTAL);
454 }
455
456 rrddim_set_by_pointer(st_balloon, rd_inflate, balloon_inflate);
457 rrddim_set_by_pointer(st_balloon, rd_deflate, balloon_deflate);
458 rrddim_set_by_pointer(st_balloon, rd_migrate, balloon_migrate);
459
460 rrdset_done(st_balloon);
461 }
462
463 // --------------------------------------------------------------------
464
465 if (is_mem_zswap_enabled && (do_zswapio == CONFIG_BOOLEAN_YES || do_zswapio == CONFIG_BOOLEAN_AUTO)) {
466 do_zswapio = CONFIG_BOOLEAN_YES;
467
468 static RRDSET *st_zswapio = NULL;
469 static RRDDIM *rd_in = NULL, *rd_out = NULL;
470
471 if(unlikely(!st_zswapio)) {
472 st_zswapio = rrdset_create_localhost(
473 "mem"
474 , "zswapio"
475 , NULL
476 , "zswap"
477 , NULL
478 , "ZSwap I/O"
479 , "KiB/s"
480 , PLUGIN_PROC_NAME
481 , PLUGIN_PROC_MODULE_VMSTAT_NAME
482 , NETDATA_CHART_PRIO_MEM_ZSWAPIO
483 , update_every
484 , RRDSET_TYPE_AREA
485 );
486
487 rd_in = rrddim_add(st_zswapio, "in", NULL, sysconf(_SC_PAGESIZE), 1024, RRD_ALGORITHM_INCREMENTAL);
488 rd_out = rrddim_add(st_zswapio, "out", NULL, -sysconf(_SC_PAGESIZE), 1024, RRD_ALGORITHM_INCREMENTAL);
489 }
490
491 rrddim_set_by_pointer(st_zswapio, rd_in, zswpin);
492 rrddim_set_by_pointer(st_zswapio, rd_out, zswpout);
493 rrdset_done(st_zswapio);
494 }
495
496 // --------------------------------------------------------------------
497
498 if (is_mem_ksm_enabled && (do_ksm == CONFIG_BOOLEAN_YES || do_ksm == CONFIG_BOOLEAN_AUTO)) {
499 do_ksm = CONFIG_BOOLEAN_YES;
500
501 static RRDSET *st_ksm_cow = NULL;
502 static RRDDIM *rd_swapin = NULL, *rd_write = NULL;
503
504 if(unlikely(!st_ksm_cow)) {
505 st_ksm_cow = rrdset_create_localhost(
506 "mem"
507 , "ksm_cow"
508 , NULL
509 , "ksm"
510 , NULL
511 , "KSM Copy On Write Operations"
512 , "KiB/s"
513 , PLUGIN_PROC_NAME
514 , PLUGIN_PROC_MODULE_VMSTAT_NAME
515 , NETDATA_CHART_PRIO_MEM_KSM_COW
516 , update_every
517 , RRDSET_TYPE_LINE
518 );
519
520 rd_swapin = rrddim_add(st_ksm_cow, "swapin", NULL, sysconf(_SC_PAGESIZE), 1024, RRD_ALGORITHM_INCREMENTAL);
521 rd_write = rrddim_add(st_ksm_cow, "write", NULL, sysconf(_SC_PAGESIZE), 1024, RRD_ALGORITHM_INCREMENTAL);
522 }
523
524 rrddim_set_by_pointer(st_ksm_cow, rd_swapin, ksm_swpin_copy);
525 rrddim_set_by_pointer(st_ksm_cow, rd_write, cow_ksm);
526
527 rrdset_done(st_ksm_cow);
528 }
529
530 // --------------------------------------------------------------------
531
532 if(do_thp == CONFIG_BOOLEAN_YES || do_thp == CONFIG_BOOLEAN_AUTO) {
533
534 static RRDSET *st_thp_fault = NULL;
535 static RRDDIM *rd_alloc = NULL, *rd_fallback = NULL, *rd_fallback_charge = NULL;
536
537 if(unlikely(!st_thp_fault)) {
538 st_thp_fault = rrdset_create_localhost(
539 "mem"
540 , "thp_faults"
541 , NULL
542 , "hugepages"
543 , NULL
544 , "Transparent Huge Page Fault Allocations"
545 , "events/s"
546 , PLUGIN_PROC_NAME
547 , PLUGIN_PROC_MODULE_VMSTAT_NAME
548 , NETDATA_CHART_PRIO_MEM_HUGEPAGES_FAULTS
549 , update_every
550 , RRDSET_TYPE_LINE
551 );
552
553 rd_alloc = rrddim_add(st_thp_fault, "alloc", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
554 rd_fallback = rrddim_add(st_thp_fault, "fallback", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
555 rd_fallback_charge = rrddim_add(st_thp_fault, "fallback_charge", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
556 }
557
558 rrddim_set_by_pointer(st_thp_fault, rd_alloc, thp_fault_alloc);
559 rrddim_set_by_pointer(st_thp_fault, rd_fallback, thp_fault_fallback);
560 rrddim_set_by_pointer(st_thp_fault, rd_fallback_charge, thp_fault_fallback_charge);
561
562 rrdset_done(st_thp_fault);
563 }
564
565 if (do_thp == CONFIG_BOOLEAN_YES || do_thp == CONFIG_BOOLEAN_AUTO) {
566 static RRDSET *st_thp_file = NULL;
567 static RRDDIM *rd_alloc = NULL, *rd_fallback = NULL, *rd_fallback_charge = NULL, *rd_mapped = NULL;
568
569 if(unlikely(!st_thp_file)) {
570 st_thp_file = rrdset_create_localhost(
571 "mem"
572 , "thp_file"
573 , NULL
574 , "hugepages"
575 , NULL
576 , "Transparent Huge Page File Allocations"
577 , "events/s"
578 , PLUGIN_PROC_NAME
579 , PLUGIN_PROC_MODULE_VMSTAT_NAME
580 , NETDATA_CHART_PRIO_MEM_HUGEPAGES_FILE
581 , update_every
582 , RRDSET_TYPE_LINE
583 );
584
585 rd_alloc = rrddim_add(st_thp_file, "alloc", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
586 rd_fallback = rrddim_add(st_thp_file, "fallback", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
587 rd_mapped = rrddim_add(st_thp_file, "mapped", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
588 rd_fallback_charge = rrddim_add(st_thp_file, "fallback_charge", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
589 }
590
591 rrddim_set_by_pointer(st_thp_file, rd_alloc, thp_file_alloc);
592 rrddim_set_by_pointer(st_thp_file, rd_fallback, thp_file_fallback);
593 rrddim_set_by_pointer(st_thp_file, rd_mapped, thp_file_fallback_charge);
594 rrddim_set_by_pointer(st_thp_file, rd_fallback_charge, thp_file_fallback_charge);
595
596 rrdset_done(st_thp_file);
597 }
598
599 if (do_thp == CONFIG_BOOLEAN_YES || do_thp == CONFIG_BOOLEAN_AUTO) {
600 static RRDSET *st_thp_zero = NULL;
601 static RRDDIM *rd_alloc = NULL, *rd_failed = NULL;
602
603 if(unlikely(!st_thp_zero)) {
604 st_thp_zero = rrdset_create_localhost(
605 "mem"
606 , "thp_zero"
607 , NULL
608 , "hugepages"
609 , NULL
610 , "Transparent Huge Zero Page Allocations"
611 , "events/s"
612 , PLUGIN_PROC_NAME
613 , PLUGIN_PROC_MODULE_VMSTAT_NAME
614 , NETDATA_CHART_PRIO_MEM_HUGEPAGES_ZERO
615 , update_every
616 , RRDSET_TYPE_LINE
617 );
618
619 rd_alloc = rrddim_add(st_thp_zero, "alloc", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
620 rd_failed = rrddim_add(st_thp_zero, "failed", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
621 }
622
623 rrddim_set_by_pointer(st_thp_zero, rd_alloc, thp_zero_page_alloc);
624 rrddim_set_by_pointer(st_thp_zero, rd_failed, thp_zero_page_alloc_failed);
625
626 rrdset_done(st_thp_zero);
627 }
628
629 if (do_thp == CONFIG_BOOLEAN_YES || do_thp == CONFIG_BOOLEAN_AUTO) {
630 static RRDSET *st_khugepaged = NULL;
631 static RRDDIM *rd_alloc = NULL, *rd_failed = NULL;
632
633 if(unlikely(!st_khugepaged)) {
634 st_khugepaged = rrdset_create_localhost(
635 "mem"
636 , "thp_collapse"
637 , NULL
638 , "hugepages"
639 , NULL
640 , "Transparent Huge Pages Collapsed by khugepaged"
641 , "events/s"
642 , PLUGIN_PROC_NAME
643 , PLUGIN_PROC_MODULE_VMSTAT_NAME
644 , NETDATA_CHART_PRIO_MEM_HUGEPAGES_KHUGEPAGED
645 , update_every
646 , RRDSET_TYPE_LINE
647 );
648
649 rd_alloc = rrddim_add(st_khugepaged, "alloc", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
650 rd_failed = rrddim_add(st_khugepaged, "failed", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
651 }
652
653 rrddim_set_by_pointer(st_khugepaged, rd_alloc, thp_collapse_alloc);
654 rrddim_set_by_pointer(st_khugepaged, rd_failed, thp_collapse_alloc_failed);
655
656 rrdset_done(st_khugepaged);
657 }
658
659 if (do_thp == CONFIG_BOOLEAN_YES || do_thp == CONFIG_BOOLEAN_AUTO) {
660 static RRDSET *st_thp_split = NULL;
661 static RRDDIM *rd_split = NULL, *rd_failed = NULL, *rd_deferred_split = NULL, *rd_split_pmd = NULL;
662
663 if(unlikely(!st_thp_split)) {
664 st_thp_split = rrdset_create_localhost(
665 "mem"
666 , "thp_split"
667 , NULL
668 , "hugepages"
669 , NULL
670 , "Transparent Huge Page Splits"
671 , "events/s"
672 , PLUGIN_PROC_NAME
673 , PLUGIN_PROC_MODULE_VMSTAT_NAME
674 , NETDATA_CHART_PRIO_MEM_HUGEPAGES_SPLITS
675 , update_every
676 , RRDSET_TYPE_LINE
677 );
678
679 rd_split = rrddim_add(st_thp_split, "split", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
680 rd_failed = rrddim_add(st_thp_split, "failed", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
681 rd_split_pmd = rrddim_add(st_thp_split, "split_pmd", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
682 rd_deferred_split = rrddim_add(st_thp_split, "split_deferred", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
683 }
684
685 rrddim_set_by_pointer(st_thp_split, rd_split, thp_split_page);
686 rrddim_set_by_pointer(st_thp_split, rd_failed, thp_split_page_failed);
687 rrddim_set_by_pointer(st_thp_split, rd_split_pmd, thp_split_pmd);
688 rrddim_set_by_pointer(st_thp_split, rd_deferred_split, thp_deferred_split_page);
689
690 rrdset_done(st_thp_split);
691 }
692
693 if (do_thp == CONFIG_BOOLEAN_YES || do_thp == CONFIG_BOOLEAN_AUTO) {
694 static RRDSET *st_tmp_swapout = NULL;
695 static RRDDIM *rd_swapout = NULL, *rd_fallback = NULL;
696
697 if(unlikely(!st_tmp_swapout)) {
698 st_tmp_swapout = rrdset_create_localhost(
699 "mem"
700 , "thp_swapout"
701 , NULL
702 , "hugepages"
703 , NULL
704 , "Transparent Huge Pages Swap Out"
705 , "events/s"
706 , PLUGIN_PROC_NAME
707 , PLUGIN_PROC_MODULE_VMSTAT_NAME
708 , NETDATA_CHART_PRIO_MEM_HUGEPAGES_SWAPOUT
709 , update_every
710 , RRDSET_TYPE_LINE
711 );
712
713 rd_swapout = rrddim_add(st_tmp_swapout, "swapout", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
714 rd_fallback = rrddim_add(st_tmp_swapout, "fallback", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
715 }
716
717 rrddim_set_by_pointer(st_tmp_swapout, rd_swapout, thp_swpout);
718 rrddim_set_by_pointer(st_tmp_swapout, rd_fallback, thp_swpout_fallback);
719
720 rrdset_done(st_tmp_swapout);
721 }
722
723 if (do_thp == CONFIG_BOOLEAN_YES || do_thp == CONFIG_BOOLEAN_AUTO) {
724 static RRDSET *st_thp_compact = NULL;
725 static RRDDIM *rd_success = NULL, *rd_fail = NULL, *rd_stall = NULL;
726
727 if(unlikely(!st_thp_compact)) {
728 st_thp_compact = rrdset_create_localhost(
729 "mem"
730 , "thp_compact"
731 , NULL
732 , "hugepages"
733 , NULL
734 , "Transparent Huge Pages Compaction"
735 , "events/s"
736 , PLUGIN_PROC_NAME
737 , PLUGIN_PROC_MODULE_VMSTAT_NAME
738 , NETDATA_CHART_PRIO_MEM_HUGEPAGES_COMPACT
739 , update_every
740 , RRDSET_TYPE_LINE
741 );
742
743 rd_success = rrddim_add(st_thp_compact, "success", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
744 rd_fail = rrddim_add(st_thp_compact, "fail", NULL, -1, 1, RRD_ALGORITHM_INCREMENTAL);
745 rd_stall = rrddim_add(st_thp_compact, "stall", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
746 }
747
748 rrddim_set_by_pointer(st_thp_compact, rd_success, compact_success);
749 rrddim_set_by_pointer(st_thp_compact, rd_fail, compact_fail);
750 rrddim_set_by_pointer(st_thp_compact, rd_stall, compact_stall);
751
752 rrdset_done(st_thp_compact);
753 }
754
755 return 0;
756 }
757