]> arthur.barton.de Git - netdata.git/blob - src/sys_kernel_mm_ksm.c
layout: remove executable from unrelated files
[netdata.git] / src / sys_kernel_mm_ksm.c
1 #ifdef HAVE_CONFIG_H
2 #include <config.h>
3 #endif
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7
8 #include "common.h"
9 #include "log.h"
10 #include "appconfig.h"
11 #include "procfile.h"
12 #include "rrd.h"
13 #include "plugin_proc.h"
14
15 typedef struct name_value {
16         char filename[FILENAME_MAX + 1];
17         unsigned long long value;
18 } NAME_VALUE;
19
20 #define PAGES_SHARED 0
21 #define PAGES_SHARING 1
22 #define PAGES_UNSHARED 2
23 #define PAGES_VOLATILE 3
24 #define PAGES_TO_SCAN 4
25
26 NAME_VALUE values[] = {
27                 [PAGES_SHARED] = { "/sys/kernel/mm/ksm/pages_shared", 0ULL },
28                 [PAGES_SHARING] = { "/sys/kernel/mm/ksm/pages_sharing", 0ULL },
29                 [PAGES_UNSHARED] = { "/sys/kernel/mm/ksm/pages_unshared", 0ULL },
30                 [PAGES_VOLATILE] = { "/sys/kernel/mm/ksm/pages_volatile", 0ULL },
31                 [PAGES_TO_SCAN] = { "/sys/kernel/mm/ksm/pages_to_scan", 0ULL },
32 };
33
34 int do_sys_kernel_mm_ksm(int update_every, unsigned long long dt) {
35         static procfile *ff_pages_shared = NULL, *ff_pages_sharing = NULL, *ff_pages_unshared = NULL, *ff_pages_volatile = NULL, *ff_pages_to_scan = NULL;
36         static long page_size = -1;
37
38         if(dt) {};
39
40         if(page_size == -1)
41                 page_size = sysconf(_SC_PAGESIZE);
42
43         if(!ff_pages_shared) {
44                 snprintf(values[PAGES_SHARED].filename, FILENAME_MAX, "%s%s", global_host_prefix, "/sys/kernel/mm/ksm/pages_shared");
45                 snprintf(values[PAGES_SHARED].filename, FILENAME_MAX, "%s", config_get("plugin:proc:/sys/kernel/mm/ksm", "/sys/kernel/mm/ksm/pages_shared", values[PAGES_SHARED].filename));
46                 ff_pages_shared = procfile_open(values[PAGES_SHARED].filename, " \t:", PROCFILE_FLAG_DEFAULT);
47         }
48
49         if(!ff_pages_sharing) {
50                 snprintf(values[PAGES_SHARING].filename, FILENAME_MAX, "%s%s", global_host_prefix, "/sys/kernel/mm/ksm/pages_sharing");
51                 snprintf(values[PAGES_SHARING].filename, FILENAME_MAX, "%s", config_get("plugin:proc:/sys/kernel/mm/ksm", "/sys/kernel/mm/ksm/pages_sharing", values[PAGES_SHARING].filename));
52                 ff_pages_sharing = procfile_open(values[PAGES_SHARING].filename, " \t:", PROCFILE_FLAG_DEFAULT);
53         }
54
55         if(!ff_pages_unshared) {
56                 snprintf(values[PAGES_UNSHARED].filename, FILENAME_MAX, "%s%s", global_host_prefix, "/sys/kernel/mm/ksm/pages_unshared");
57                 snprintf(values[PAGES_UNSHARED].filename, FILENAME_MAX, "%s", config_get("plugin:proc:/sys/kernel/mm/ksm", "/sys/kernel/mm/ksm/pages_unshared", values[PAGES_UNSHARED].filename));
58                 ff_pages_unshared = procfile_open(values[PAGES_UNSHARED].filename, " \t:", PROCFILE_FLAG_DEFAULT);
59         }
60
61         if(!ff_pages_volatile) {
62                 snprintf(values[PAGES_VOLATILE].filename, FILENAME_MAX, "%s%s", global_host_prefix, "/sys/kernel/mm/ksm/pages_volatile");
63                 snprintf(values[PAGES_VOLATILE].filename, FILENAME_MAX, "%s", config_get("plugin:proc:/sys/kernel/mm/ksm", "/sys/kernel/mm/ksm/pages_volatile", values[PAGES_VOLATILE].filename));
64                 ff_pages_volatile = procfile_open(values[PAGES_VOLATILE].filename, " \t:", PROCFILE_FLAG_DEFAULT);
65         }
66
67         if(!ff_pages_to_scan) {
68                 snprintf(values[PAGES_TO_SCAN].filename, FILENAME_MAX, "%s%s", global_host_prefix, "/sys/kernel/mm/ksm/pages_to_scan");
69                 snprintf(values[PAGES_TO_SCAN].filename, FILENAME_MAX, "%s", config_get("plugin:proc:/sys/kernel/mm/ksm", "/sys/kernel/mm/ksm/pages_to_scan", values[PAGES_TO_SCAN].filename));
70                 ff_pages_to_scan = procfile_open(values[PAGES_TO_SCAN].filename, " \t:", PROCFILE_FLAG_DEFAULT);
71         }
72
73         if(!ff_pages_shared || !ff_pages_sharing || !ff_pages_unshared || !ff_pages_volatile || !ff_pages_to_scan) return 1;
74
75         unsigned long long pages_shared = 0, pages_sharing = 0, pages_unshared = 0, pages_volatile = 0, pages_to_scan = 0, offered = 0, saved = 0;
76
77         ff_pages_shared = procfile_readall(ff_pages_shared);
78         if(!ff_pages_shared) return 0; // we return 0, so that we will retry to open it next time
79         pages_shared = strtoull(procfile_lineword(ff_pages_shared, 0, 0), NULL, 10);
80
81         ff_pages_sharing = procfile_readall(ff_pages_sharing);
82         if(!ff_pages_sharing) return 0; // we return 0, so that we will retry to open it next time
83         pages_sharing = strtoull(procfile_lineword(ff_pages_sharing, 0, 0), NULL, 10);
84
85         ff_pages_unshared = procfile_readall(ff_pages_unshared);
86         if(!ff_pages_unshared) return 0; // we return 0, so that we will retry to open it next time
87         pages_unshared = strtoull(procfile_lineword(ff_pages_unshared, 0, 0), NULL, 10);
88
89         ff_pages_volatile = procfile_readall(ff_pages_volatile);
90         if(!ff_pages_volatile) return 0; // we return 0, so that we will retry to open it next time
91         pages_volatile = strtoull(procfile_lineword(ff_pages_volatile, 0, 0), NULL, 10);
92
93         ff_pages_to_scan = procfile_readall(ff_pages_to_scan);
94         if(!ff_pages_to_scan) return 0; // we return 0, so that we will retry to open it next time
95         pages_to_scan = strtoull(procfile_lineword(ff_pages_to_scan, 0, 0), NULL, 10);
96
97         offered = pages_sharing + pages_unshared + pages_volatile;
98         saved = pages_sharing - pages_shared;
99
100         if(!offered || !pages_to_scan) return 0;
101
102         RRDSET *st;
103
104         // --------------------------------------------------------------------
105
106         st = rrdset_find("mem.ksm");
107         if(!st) {
108                 st = rrdset_create("mem", "ksm", NULL, "ksm", NULL, "Kernel Same Page Merging", "MB", 5000, update_every, RRDSET_TYPE_AREA);
109
110                 rrddim_add(st, "shared", NULL, 1, 1024 * 1024, RRDDIM_ABSOLUTE);
111                 rrddim_add(st, "unshared", NULL, -1, 1024 * 1024, RRDDIM_ABSOLUTE);
112                 rrddim_add(st, "sharing", NULL, 1, 1024 * 1024, RRDDIM_ABSOLUTE);
113                 rrddim_add(st, "volatile", NULL, -1, 1024 * 1024, RRDDIM_ABSOLUTE);
114                 rrddim_add(st, "to_scan", "to scan", -1, 1024 * 1024, RRDDIM_ABSOLUTE);
115         }
116         else rrdset_next(st);
117
118         rrddim_set(st, "shared", pages_shared * page_size);
119         rrddim_set(st, "unshared", pages_unshared * page_size);
120         rrddim_set(st, "sharing", pages_sharing * page_size);
121         rrddim_set(st, "volatile", pages_volatile * page_size);
122         rrddim_set(st, "to_scan", pages_to_scan * page_size);
123         rrdset_done(st);
124
125         st = rrdset_find("mem.ksm_savings");
126         if(!st) {
127                 st = rrdset_create("mem", "ksm_savings", NULL, "ksm", NULL, "Kernel Same Page Merging Savings", "MB", 5001, update_every, RRDSET_TYPE_AREA);
128
129                 rrddim_add(st, "savings", NULL, -1, 1024 * 1024, RRDDIM_ABSOLUTE);
130                 rrddim_add(st, "offered", NULL, 1, 1024 * 1024, RRDDIM_ABSOLUTE);
131         }
132         else rrdset_next(st);
133
134         rrddim_set(st, "savings", saved * page_size);
135         rrddim_set(st, "offered", offered * page_size);
136         rrdset_done(st);
137
138         st = rrdset_find("mem.ksm_ratios");
139         if(!st) {
140                 st = rrdset_create("mem", "ksm_ratios", NULL, "ksm", NULL, "Kernel Same Page Merging Effectiveness", "percentage", 5002, update_every, RRDSET_TYPE_LINE);
141
142                 rrddim_add(st, "savings", NULL, 1, 10000, RRDDIM_ABSOLUTE);
143         }
144         else rrdset_next(st);
145
146         rrddim_set(st, "savings", (saved * 1000000) / offered);
147         rrdset_done(st);
148
149         return 0;
150 }