typedef struct {
cdtime_t time;
+ cdtime_t interval;
+ bool finalized;
+
usage_state_t *states;
size_t states_num;
+
+ usage_state_t global[STATE_MAX];
} usage_t;
__attribute__((unused)) static int usage_init(usage_t *u, cdtime_t now) {
return EINVAL;
}
+ if (u->time != 0 && u->time < now) {
+ u->interval = now - u->time;
+ }
u->time = now;
+ u->finalized = false;
for (size_t i = 0; i < u->states_num; i++) {
+ u->states[i].rate = 0;
u->states[i].has_value = false;
}
+ for (state_t s = 0; s < STATE_MAX; s++) {
+ u->global[s].rate = 0;
+ u->global[s].has_value = false;
+ }
+
return 0;
}
return 0;
}
-static gauge_t usage_rate(usage_t u, size_t cpu, state_t state);
-
-static gauge_t usage_active_rate(usage_t u, size_t cpu) {
- size_t index = (cpu * STATE_MAX) + STATE_ACTIVE;
- if (index >= u.states_num) {
- return NAN;
+static void usage_finalize(usage_t *u) {
+ if (u->finalized) {
+ return;
}
- usage_state_t us = u.states[index];
- if (us.has_value) {
- return us.rate;
- }
+ size_t cpu_num = u->states_num / STATE_MAX;
+ for (size_t cpu = 0; cpu < cpu_num; cpu++) {
+ size_t active_index = (cpu * STATE_MAX) + STATE_ACTIVE;
+ usage_state_t *active = u->states + active_index;
- us.rate = 0;
- for (state_t s = 0; s < STATE_IDLE; s++) {
- gauge_t rate = usage_rate(u, cpu, s);
- if (isnan(rate)) {
- continue;
- }
+ active->rate = 0;
+ active->has_value = false;
- us.rate += rate;
- us.has_value = true;
- }
+ for (state_t s = 0; s < STATE_ACTIVE; s++) {
+ size_t index = (cpu * STATE_MAX) + s;
+ usage_state_t *us = u->states + index;
- return us.has_value ? us.rate : NAN;
-}
+ if (!us->has_value) {
+ continue;
+ }
-static gauge_t usage_global_rate(usage_t u, state_t state) {
- size_t cpu_num = u.states_num / STATE_MAX;
- usage_state_t us = {0};
- for (size_t i = 0; i < cpu_num; i++) {
- gauge_t rate = usage_rate(u, i, state);
- if (isnan(rate)) {
- continue;
+ u->global[s].rate += us->rate;
+ u->global[s].has_value = true;
+
+ if (s != STATE_IDLE) {
+ active->rate += us->rate;
+ active->has_value = true;
+ }
}
- us.rate += rate;
- us.has_value = true;
+ if (active->has_value) {
+ u->global[STATE_ACTIVE].rate += active->rate;
+ u->global[STATE_ACTIVE].has_value = true;
+ }
}
- return us.has_value ? us.rate : NAN;
+ u->finalized = true;
}
-static gauge_t usage_rate(usage_t u, size_t cpu, state_t state) {
- if (state == STATE_ACTIVE) {
- return usage_active_rate(u, cpu);
- }
+static gauge_t usage_rate(usage_t *u, size_t cpu, state_t state) {
+ usage_finalize(u);
size_t index = (cpu * STATE_MAX) + state;
- if (index >= u.states_num) {
+ if (index >= u->states_num) {
return NAN;
}
- usage_state_t us = u.states[index];
+ usage_state_t us = u->states[index];
return us.has_value ? us.rate : NAN;
}
+__attribute__((unused)) static gauge_t usage_active_rate(usage_t *u,
+ size_t cpu) {
+ return usage_rate(u, cpu, STATE_ACTIVE);
+}
+
+static gauge_t usage_global_rate(usage_t *u, state_t state) {
+ usage_finalize(u);
+
+ return u->global[state].has_value ? u->global[state].rate : NAN;
+}
+
__attribute__((unused)) static void usage_reset(usage_t *u) {
if (u == NULL) {
return;
}
free(u->states);
- u->states = NULL;
- u->states_num = 0;
+ memset(u, 0, sizeof(*u));
}
-__attribute__((unused)) static gauge_t usage_ratio(usage_t u, size_t cpu,
+__attribute__((unused)) static gauge_t usage_ratio(usage_t *u, size_t cpu,
state_t state) {
gauge_t global_rate =
usage_global_rate(u, STATE_ACTIVE) + usage_global_rate(u, STATE_IDLE);
return usage_rate(u, cpu, state) / global_rate;
}
-__attribute__((unused)) static gauge_t usage_global_ratio(usage_t u, state_t state) {
+__attribute__((unused)) static gauge_t usage_global_ratio(usage_t *u,
+ state_t state) {
gauge_t global_rate =
usage_global_rate(u, STATE_ACTIVE) + usage_global_rate(u, STATE_IDLE);
return usage_global_rate(u, state) / global_rate;
usage_record(&usage, 0, STATE_USER, count_t0);
// Unable to calculate a rate with a single data point.
- EXPECT_EQ_DOUBLE(NAN, usage_rate(usage, 0, STATE_USER));
- EXPECT_EQ_DOUBLE(NAN, usage_rate(usage, 0, STATE_ACTIVE));
+ EXPECT_EQ_DOUBLE(NAN, usage_rate(&usage, 0, STATE_USER));
+ EXPECT_EQ_DOUBLE(NAN, usage_rate(&usage, 0, STATE_ACTIVE));
cdtime_t t1 = t0 + TIME_T_TO_CDTIME_T(10);
derive_t count_t1 = count_t0 + 100;
usage_init(&usage, t1);
usage_record(&usage, 0, STATE_USER, count_t1);
- EXPECT_EQ_DOUBLE(want_rate, usage_rate(usage, 0, STATE_USER));
- EXPECT_EQ_DOUBLE(want_rate, usage_rate(usage, 0, STATE_ACTIVE));
+ EXPECT_EQ_DOUBLE(want_rate, usage_rate(&usage, 0, STATE_USER));
+ EXPECT_EQ_DOUBLE(want_rate, usage_rate(&usage, 0, STATE_ACTIVE));
// States that we have not set should be NAN
for (state_t s = 0; s < STATE_ACTIVE; s++) {
if (s == STATE_USER) {
continue;
}
- EXPECT_EQ_DOUBLE(NAN, usage_rate(usage, 0, s));
+ EXPECT_EQ_DOUBLE(NAN, usage_rate(&usage, 0, s));
}
usage_reset(&usage);
active_increment += increment;
}
gauge_t want_ratio = ((gauge_t)increment) / ((gauge_t)global_increment);
- EXPECT_EQ_DOUBLE(want_ratio, usage_ratio(usage, cpu, s));
+ EXPECT_EQ_DOUBLE(want_ratio, usage_ratio(&usage, cpu, s));
}
gauge_t want_active_ratio =
((gauge_t)active_increment) / ((gauge_t)global_increment);
- EXPECT_EQ_DOUBLE(want_active_ratio, usage_ratio(usage, cpu, STATE_ACTIVE));
+ EXPECT_EQ_DOUBLE(want_active_ratio, usage_ratio(&usage, cpu, STATE_ACTIVE));
}
gauge_t sum = 0;
for (size_t cpu = 0; cpu < 4; cpu++) {
for (state_t s = 0; s < STATE_ACTIVE; s++) {
- gauge_t rate = usage_ratio(usage, cpu, s);
+ gauge_t rate = usage_ratio(&usage, cpu, s);
sum += rate;
}
}
usage_record(&usage, 0, STATE_IDLE, idle_t0);
// Unable to calculate a rate with a single data point.
- EXPECT_EQ_DOUBLE(NAN, usage_rate(usage, 0, STATE_USER));
- EXPECT_EQ_DOUBLE(NAN, usage_rate(usage, 0, STATE_SYSTEM));
- EXPECT_EQ_DOUBLE(NAN, usage_rate(usage, 0, STATE_IDLE));
- EXPECT_EQ_DOUBLE(NAN, usage_rate(usage, 0, STATE_ACTIVE));
- EXPECT_EQ_DOUBLE(NAN, usage_active_rate(usage, 0));
+ EXPECT_EQ_DOUBLE(NAN, usage_rate(&usage, 0, STATE_USER));
+ EXPECT_EQ_DOUBLE(NAN, usage_rate(&usage, 0, STATE_SYSTEM));
+ EXPECT_EQ_DOUBLE(NAN, usage_rate(&usage, 0, STATE_IDLE));
+ EXPECT_EQ_DOUBLE(NAN, usage_rate(&usage, 0, STATE_ACTIVE));
+ EXPECT_EQ_DOUBLE(NAN, usage_active_rate(&usage, 0));
cdtime_t t1 = t0 + TIME_T_TO_CDTIME_T(10);
derive_t user_t1 = user_t0 + 200;
usage_record(&usage, 0, STATE_SYSTEM, syst_t1);
usage_record(&usage, 0, STATE_IDLE, idle_t1);
- EXPECT_EQ_DOUBLE(want_user_rate, usage_rate(usage, 0, STATE_USER));
- EXPECT_EQ_DOUBLE(want_syst_rate, usage_rate(usage, 0, STATE_SYSTEM));
- EXPECT_EQ_DOUBLE(want_idle_rate, usage_rate(usage, 0, STATE_IDLE));
- EXPECT_EQ_DOUBLE(want_active_rate, usage_rate(usage, 0, STATE_ACTIVE));
- EXPECT_EQ_DOUBLE(want_active_rate, usage_active_rate(usage, 0));
+ EXPECT_EQ_DOUBLE(want_user_rate, usage_rate(&usage, 0, STATE_USER));
+ EXPECT_EQ_DOUBLE(want_syst_rate, usage_rate(&usage, 0, STATE_SYSTEM));
+ EXPECT_EQ_DOUBLE(want_idle_rate, usage_rate(&usage, 0, STATE_IDLE));
+ EXPECT_EQ_DOUBLE(want_active_rate, usage_rate(&usage, 0, STATE_ACTIVE));
+ EXPECT_EQ_DOUBLE(want_active_rate, usage_active_rate(&usage, 0));
usage_reset(&usage);
return 0;
usage_record(&usage, 1, STATE_USER, cpu1_t0);
// Unable to calculate a rate with a single data point.
- EXPECT_EQ_DOUBLE(NAN, usage_rate(usage, 0, STATE_USER));
- EXPECT_EQ_DOUBLE(NAN, usage_rate(usage, 1, STATE_USER));
- EXPECT_EQ_DOUBLE(NAN, usage_global_rate(usage, STATE_USER));
- EXPECT_EQ_DOUBLE(NAN, usage_global_rate(usage, STATE_ACTIVE));
+ EXPECT_EQ_DOUBLE(NAN, usage_rate(&usage, 0, STATE_USER));
+ EXPECT_EQ_DOUBLE(NAN, usage_rate(&usage, 1, STATE_USER));
+ EXPECT_EQ_DOUBLE(NAN, usage_global_rate(&usage, STATE_USER));
+ EXPECT_EQ_DOUBLE(NAN, usage_global_rate(&usage, STATE_ACTIVE));
cdtime_t t1 = t0 + TIME_T_TO_CDTIME_T(10);
derive_t cpu0_t1 = cpu0_t0 + 300;
usage_record(&usage, 0, STATE_USER, cpu0_t1);
usage_record(&usage, 1, STATE_USER, cpu1_t1);
- EXPECT_EQ_DOUBLE(want_cpu0_rate, usage_rate(usage, 0, STATE_USER));
- EXPECT_EQ_DOUBLE(want_cpu1_rate, usage_rate(usage, 1, STATE_USER));
- EXPECT_EQ_DOUBLE(want_global_rate, usage_global_rate(usage, STATE_USER));
- EXPECT_EQ_DOUBLE(want_global_rate, usage_global_rate(usage, STATE_ACTIVE));
+ EXPECT_EQ_DOUBLE(want_cpu0_rate, usage_rate(&usage, 0, STATE_USER));
+ EXPECT_EQ_DOUBLE(want_cpu1_rate, usage_rate(&usage, 1, STATE_USER));
+ EXPECT_EQ_DOUBLE(want_global_rate, usage_global_rate(&usage, STATE_USER));
+ EXPECT_EQ_DOUBLE(want_global_rate, usage_global_rate(&usage, STATE_ACTIVE));
usage_reset(&usage);
return 0;
}
gauge_t want_state_ratio =
((gauge_t)state_increment) / ((gauge_t)global_increment);
- EXPECT_EQ_DOUBLE(want_state_ratio, usage_global_ratio(usage, s));
+ EXPECT_EQ_DOUBLE(want_state_ratio, usage_global_ratio(&usage, s));
if (s != STATE_IDLE) {
global_active_increment += state_increment;
gauge_t want_global_active_ratio =
((gauge_t)global_active_increment) / ((gauge_t)global_increment);
EXPECT_EQ_DOUBLE(want_global_active_ratio,
- usage_global_ratio(usage, STATE_ACTIVE));
+ usage_global_ratio(&usage, STATE_ACTIVE));
EXPECT_EQ_DOUBLE(1.0 - want_global_active_ratio,
- usage_global_ratio(usage, STATE_IDLE));
+ usage_global_ratio(&usage, STATE_IDLE));
usage_reset(&usage);
return 0;