@cryptotaxi247 / netdata-1 / commits / 58eba31ad

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;