optimize cpu metrics collection to avoid repeating searches in the database
Costa Tsaousis (ktsaou) committed
Sep 5, 2017 at 21:36 UTC
58eba31add4cde5068e77106342f1c1d7d0e8768
1 file changed
+116
-89
src/proc_stat.c
+116
-89
@@ -1,8 +1,25 @@
1
#include "common.h"
2
3
+struct cpu_chart {
4
+ RRDSET *st;
5
+ RRDDIM *rd_user;
6
+ RRDDIM *rd_nice;
7
+ RRDDIM *rd_system;
8
+ RRDDIM *rd_idle;
9
+ RRDDIM *rd_iowait;
10
+ RRDDIM *rd_irq;
11
+ RRDDIM *rd_softirq;
12
+ RRDDIM *rd_steal;
13
+ RRDDIM *rd_guest;
14
+ RRDDIM *rd_guest_nice;
15
+
16
+};
17
+
18
int do_proc_stat(int update_every, usec_t dt) {
19
(void)dt;
20
21
+ static struct cpu_chart *all_cpu_charts = NULL;
22
+ static size_t all_cpu_charts_size = 0;
23
static procfile *ff = NULL;
24
static int do_cpu = -1, do_cpu_cores = -1, do_interrupts = -1, do_context = -1, do_forks = -1, do_processes = -1;
25
static uint32_t hash_intr, hash_ctxt, hash_processes, hash_procs_running, hash_procs_blocked;
@@ -36,7 +53,6 @@ int do_proc_stat(int update_every, usec_t dt) {
53
size_t words;
54
55
unsigned long long processes = 0, running = 0 , blocked = 0;
39
- RRDSET *st;
56
57
for(l = 0; l < lines ;l++) {
58
char *row_key = procfile_lineword(ff, l, 0);
@@ -53,6 +69,7 @@ int do_proc_stat(int update_every, usec_t dt) {
69
char *id;
70
unsigned long long user = 0, nice = 0, system = 0, idle = 0, iowait = 0, irq = 0, softirq = 0, steal = 0, guest = 0, guest_nice = 0;
71
72
+ size_t core = (row_key[3] == '\0') ? 0 : str2ul(&row_key[3]) + 1;
73
id = row_key;
74
user = str2ull(procfile_lineword(ff, l, 1));
75
nice = str2ull(procfile_lineword(ff, l, 2));
@@ -71,99 +88,104 @@ int do_proc_stat(int update_every, usec_t dt) {
88
89
char *title, *type, *context, *family;
90
long priority;
74
- int isthistotal;
75
-
76
- if(unlikely(strcmp(id, "cpu")) == 0) {
77
- title = "Total CPU utilization";
78
- type = "system";
79
- context = "system.cpu";
80
- family = id;
81
- priority = 100;
82
- isthistotal = 1;
83
- }
84
- else {
85
- title = "Core utilization";
86
- type = "cpu";
87
- context = "cpu.cpu";
88
- family = "utilization";
89
- priority = 1000;
90
- isthistotal = 0;
91
- }
91
93
- if(likely((isthistotal && do_cpu) || (!isthistotal && do_cpu_cores))) {
94
- st = rrdset_find_bytype_localhost(type, id);
95
- if(unlikely(!st)) {
96
- st = rrdset_create_localhost(type, id, NULL, family, context, title, "percentage", priority
97
- , update_every, RRDSET_TYPE_STACKED);
92
+ if(core >= all_cpu_charts_size) {
93
+ size_t old_cpu_charts_size = all_cpu_charts_size;
94
+ all_cpu_charts_size = core + 1;
95
+ all_cpu_charts = reallocz(all_cpu_charts, sizeof(struct cpu_chart) * all_cpu_charts_size);
96
+ memset(&all_cpu_charts[old_cpu_charts_size], 0, sizeof(struct cpu_chart) * (all_cpu_charts_size - old_cpu_charts_size));
97
+ }
98
+ struct cpu_chart *cpu_chart = &all_cpu_charts[core];
99
+
100
+ if(likely((core == 0 && do_cpu) || (core > 0 && do_cpu_cores))) {
101
+ if(unlikely(!cpu_chart->st)) {
102
+ if(core == 0) {
103
+ title = "Total CPU utilization";
104
+ type = "system";
105
+ context = "system.cpu";
106
+ family = id;
107
+ priority = 100;
108
+ }
109
+ else {
110
+ title = "Core utilization";
111
+ type = "cpu";
112
+ context = "cpu.cpu";
113
+ family = "utilization";
114
+ priority = 1000;
115
+
116
+ // FIXME: check for /sys/devices/system/cpu/cpu*/cpufreq/scaling_cur_freq
117
+ // FIXME: check for /sys/devices/system/cpu/cpu*/cpufreq/stats/time_in_state
118
+ // FIXME: check for /sys/devices/system/cpu/cpu*/thermal_throttle/core_throttle_count
119
+ // FIXME: check for /sys/devices/system/cpu/cpu*/thermal_throttle/package_throttle_count
120
+ }
121
+
122
+ cpu_chart->st = rrdset_create_localhost(type, id, NULL, family, context, title, "percentage", priority, update_every, RRDSET_TYPE_STACKED);
123
124
long multiplier = 1;
125
long divisor = 1; // sysconf(_SC_CLK_TCK);
126
102
- rrddim_add(st, "guest_nice", NULL, multiplier, divisor, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
103
- rrddim_add(st, "guest", NULL, multiplier, divisor, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
104
- rrddim_add(st, "steal", NULL, multiplier, divisor, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
105
- rrddim_add(st, "softirq", NULL, multiplier, divisor, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
106
- rrddim_add(st, "irq", NULL, multiplier, divisor, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
107
- rrddim_add(st, "user", NULL, multiplier, divisor, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
108
- rrddim_add(st, "system", NULL, multiplier, divisor, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
109
- rrddim_add(st, "nice", NULL, multiplier, divisor, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
110
- rrddim_add(st, "iowait", NULL, multiplier, divisor, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
111
-
112
- rrddim_add(st, "idle", NULL, multiplier, divisor, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
113
- rrddim_hide(st, "idle");
127
+ cpu_chart->rd_guest_nice = rrddim_add(cpu_chart->st, "guest_nice", NULL, multiplier, divisor, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
128
+ cpu_chart->rd_guest = rrddim_add(cpu_chart->st, "guest", NULL, multiplier, divisor, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
129
+ cpu_chart->rd_steal = rrddim_add(cpu_chart->st, "steal", NULL, multiplier, divisor, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
130
+ cpu_chart->rd_softirq = rrddim_add(cpu_chart->st, "softirq", NULL, multiplier, divisor, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
131
+ cpu_chart->rd_irq = rrddim_add(cpu_chart->st, "irq", NULL, multiplier, divisor, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
132
+ cpu_chart->rd_user = rrddim_add(cpu_chart->st, "user", NULL, multiplier, divisor, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
133
+ cpu_chart->rd_system = rrddim_add(cpu_chart->st, "system", NULL, multiplier, divisor, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
134
+ cpu_chart->rd_nice = rrddim_add(cpu_chart->st, "nice", NULL, multiplier, divisor, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
135
+ cpu_chart->rd_iowait = rrddim_add(cpu_chart->st, "iowait", NULL, multiplier, divisor, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
136
+ cpu_chart->rd_idle = rrddim_add(cpu_chart->st, "idle", NULL, multiplier, divisor, RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL);
137
+ rrddim_hide(cpu_chart->st, "idle");
138
}
115
- else rrdset_next(st);
116
-
117
- rrddim_set(st, "user", user);
118
- rrddim_set(st, "nice", nice);
119
- rrddim_set(st, "system", system);
120
- rrddim_set(st, "idle", idle);
121
- rrddim_set(st, "iowait", iowait);
122
- rrddim_set(st, "irq", irq);
123
- rrddim_set(st, "softirq", softirq);
124
- rrddim_set(st, "steal", steal);
125
- rrddim_set(st, "guest", guest);
126
- rrddim_set(st, "guest_nice", guest_nice);
127
- rrdset_done(st);
139
+ else rrdset_next(cpu_chart->st);
140
+
141
+ rrddim_set_by_pointer(cpu_chart->st, cpu_chart->rd_user, user);
142
+ rrddim_set_by_pointer(cpu_chart->st, cpu_chart->rd_nice, nice);
143
+ rrddim_set_by_pointer(cpu_chart->st, cpu_chart->rd_system, system);
144
+ rrddim_set_by_pointer(cpu_chart->st, cpu_chart->rd_idle, idle);
145
+ rrddim_set_by_pointer(cpu_chart->st, cpu_chart->rd_iowait, iowait);
146
+ rrddim_set_by_pointer(cpu_chart->st, cpu_chart->rd_irq, irq);
147
+ rrddim_set_by_pointer(cpu_chart->st, cpu_chart->rd_softirq, softirq);
148
+ rrddim_set_by_pointer(cpu_chart->st, cpu_chart->rd_steal, steal);
149
+ rrddim_set_by_pointer(cpu_chart->st, cpu_chart->rd_guest, guest);
150
+ rrddim_set_by_pointer(cpu_chart->st, cpu_chart->rd_guest_nice, guest_nice);
151
+ rrdset_done(cpu_chart->st);
152
}
153
}
154
else if(unlikely(hash == hash_intr && strcmp(row_key, "intr") == 0)) {
131
- unsigned long long value = str2ull(procfile_lineword(ff, l, 1));
132
-
133
- // --------------------------------------------------------------------
134
-
155
if(likely(do_interrupts)) {
136
- st = rrdset_find_bytype_localhost("system", "intr");
137
- if(unlikely(!st)) {
138
- st = rrdset_create_localhost("system", "intr", NULL, "interrupts", NULL, "CPU Interrupts"
156
+ static RRDSET *st_intr = NULL;
157
+ static RRDDIM *rd_interrupts = NULL;
158
+ unsigned long long value = str2ull(procfile_lineword(ff, l, 1));
159
+
160
+ if(unlikely(!st_intr)) {
161
+ st_intr = rrdset_create_localhost("system", "intr", NULL, "interrupts", NULL, "CPU Interrupts"
162
, "interrupts/s", 900, update_every, RRDSET_TYPE_LINE);
140
- rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
163
+ rrdset_flag_set(st_intr, RRDSET_FLAG_DETAIL);
164
142
- rrddim_add(st, "interrupts", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
165
+ rd_interrupts = rrddim_add(st_intr, "interrupts", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
166
}
144
- else rrdset_next(st);
167
+ else rrdset_next(st_intr);
168
146
- rrddim_set(st, "interrupts", value);
147
- rrdset_done(st);
169
+ rrddim_set_by_pointer(st_intr, rd_interrupts, value);
170
+ rrdset_done(st_intr);
171
}
172
}
173
else if(unlikely(hash == hash_ctxt && strcmp(row_key, "ctxt") == 0)) {
151
- unsigned long long value = str2ull(procfile_lineword(ff, l, 1));
152
-
153
- // --------------------------------------------------------------------
154
-
174
if(likely(do_context)) {
156
- st = rrdset_find_bytype_localhost("system", "ctxt");
157
- if(unlikely(!st)) {
158
- st = rrdset_create_localhost("system", "ctxt", NULL, "processes", NULL, "CPU Context Switches"
175
+ static RRDSET *st_ctxt = NULL;
176
+ static RRDDIM *rd_switches = NULL;
177
+ unsigned long long value = str2ull(procfile_lineword(ff, l, 1));
178
+
179
+ if(unlikely(!st_ctxt)) {
180
+ st_ctxt = rrdset_create_localhost("system", "ctxt", NULL, "processes", NULL, "CPU Context Switches"
181
, "context switches/s", 800, update_every, RRDSET_TYPE_LINE);
182
161
- rrddim_add(st, "switches", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
183
+ rd_switches = rrddim_add(st_ctxt, "switches", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
184
}
163
- else rrdset_next(st);
185
+ else rrdset_next(st_ctxt);
186
165
- rrddim_set(st, "switches", value);
166
- rrdset_done(st);
187
+ rrddim_set_by_pointer(st_ctxt, rd_switches, value);
188
+ rrdset_done(st_ctxt);
189
}
190
}
191
else if(unlikely(hash == hash_processes && !processes && strcmp(row_key, "processes") == 0)) {
@@ -180,36 +202,41 @@ int do_proc_stat(int update_every, usec_t dt) {
202
// --------------------------------------------------------------------
203
204
if(likely(do_forks)) {
183
- st = rrdset_find_bytype_localhost("system", "forks");
184
- if(unlikely(!st)) {
185
- st = rrdset_create_localhost("system", "forks", NULL, "processes", NULL, "Started Processes", "processes/s"
205
+ static RRDSET *st_forks = NULL;
206
+ static RRDDIM *rd_started = NULL;
207
+
208
+ if(unlikely(!st_forks)) {
209
+ st_forks = rrdset_create_localhost("system", "forks", NULL, "processes", NULL, "Started Processes", "processes/s"
210
, 700, update_every, RRDSET_TYPE_LINE);
187
- rrdset_flag_set(st, RRDSET_FLAG_DETAIL);
211
+ rrdset_flag_set(st_forks, RRDSET_FLAG_DETAIL);
212
189
- rrddim_add(st, "started", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
213
+ rd_started = rrddim_add(st_forks, "started", NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL);
214
}
191
- else rrdset_next(st);
215
+ else rrdset_next(st_forks);
216
193
- rrddim_set(st, "started", processes);
194
- rrdset_done(st);
217
+ rrddim_set_by_pointer(st_forks, rd_started, processes);
218
+ rrdset_done(st_forks);
219
}
220
221
// --------------------------------------------------------------------
222
223
if(likely(do_processes)) {
200
- st = rrdset_find_bytype_localhost("system", "processes");
201
- if(unlikely(!st)) {
202
- st = rrdset_create_localhost("system", "processes", NULL, "processes", NULL, "System Processes", "processes"
224
+ static RRDSET *st_processes = NULL;
225
+ static RRDDIM *rd_running = NULL;
226
+ static RRDDIM *rd_blocked = NULL;
227
+
228
+ if(unlikely(!st_processes)) {
229
+ st_processes = rrdset_create_localhost("system", "processes", NULL, "processes", NULL, "System Processes", "processes"
230
, 600, update_every, RRDSET_TYPE_LINE);
231
205
- rrddim_add(st, "running", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
206
- rrddim_add(st, "blocked", NULL, -1, 1, RRD_ALGORITHM_ABSOLUTE);
232
+ rd_running = rrddim_add(st_processes, "running", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
233
+ rd_blocked = rrddim_add(st_processes, "blocked", NULL, -1, 1, RRD_ALGORITHM_ABSOLUTE);
234
}
208
- else rrdset_next(st);
235
+ else rrdset_next(st_processes);
236
210
- rrddim_set(st, "running", running);
211
- rrddim_set(st, "blocked", blocked);
212
- rrdset_done(st);
237
+ rrddim_set_by_pointer(st_processes, rd_running, running);
238
+ rrddim_set_by_pointer(st_processes, rd_blocked, blocked);
239
+ rrdset_done(st_processes);
240
}
241
242
return 0;