diff --git a/daemon/call.c b/daemon/call.c index d8e625fe1..88264ca54 100644 --- a/daemon/call.c +++ b/daemon/call.c @@ -64,10 +64,6 @@ struct xmlrpc_helper { GQueue strings; }; - -static struct global_stats_counter rtpe_stats_intv; // copied out once per timer run - - rwlock_t rtpe_callhash_lock; GHashTable *rtpe_callhash; struct call_iterator_list rtpe_call_iterators[NUM_CALL_ITERATORS]; @@ -504,13 +500,13 @@ void call_timer(void *ptr) { struct timeval tv_start; long long run_diff_us; - // timers are run in a single thread, so no locking required here + /* timers are run in a single thread, so no locking required here */ static struct timeval last_run; static long long interval = 900000; // usec tv_start = rtpe_now; - // ready to start? + /* ready to start? */ run_diff_us = timeval_diff(&tv_start, &last_run); if (run_diff_us < interval) return; @@ -523,9 +519,7 @@ void call_timer(void *ptr) { call_timer_iterator(c, &hlp); ITERATE_CALL_LIST_NEXT_END(c); - stats_counters_calc_rate(&rtpe_stats, run_diff_us, &rtpe_stats_intv, &rtpe_stats_rate); - - // stats derived while iterating calls + /* stats derived while iterating calls */ RTPE_GAUGE_SET(transcoded_media, hlp.transcoded_media); kill_calls_timer(hlp.del_scheduled, NULL); @@ -538,12 +532,12 @@ void call_timer(void *ptr) { long long duration = timeval_diff(&tv_stop, &tv_start); ilog(LOG_DEBUG, "timer run time = %llu.%06llu sec", duration / 1000000, duration % 1000000); - // increase timer run duration if runtime was within 10% of the interval + /* increase timer run duration if runtime was within 10% of the interval */ if (duration > interval / 10) { interval *= 2; ilog(LOG_INFO, "Increasing timer run interval to %llu seconds", interval / 1000000); } - // or if the runtime was less than 2% of the interval, decrease the interval + /* or if the runtime was less than 2% of the interval, decrease the interval */ else if (interval > 1000000 && duration < interval / 50) { interval /= 2; ilog(LOG_INFO, "Decreasing timer run interval to %llu seconds", interval / 1000000); diff --git a/daemon/statistics.c b/daemon/statistics.c index c881b42b6..caff1fc7a 100644 --- a/daemon/statistics.c +++ b/daemon/statistics.c @@ -22,6 +22,7 @@ struct global_sampled_min_max rtpe_sampled_min_max; // master lifetime min/max struct global_stats_counter rtpe_stats; // total, cumulative, master struct global_stats_counter rtpe_stats_rate; // per-second, calculated once per timer run +struct global_stats_counter rtpe_stats_intv; // calculated once per sec by `call_rate_stats_updater()` // op can be CMC_INCREMENT or CMC_DECREMENT @@ -1022,11 +1023,26 @@ const char *statistics_ng(bencode_item_t *input, bencode_item_t *output) { * Separate thread for update of running min/max call counters. */ void call_rate_stats_updater(void * dummy) { + bool first_run = true; + struct timeval last_run = (struct timeval) {0,0}; + while (!rtpe_shutdown) { + struct timeval tv_start; + long long run_diff_us; + + gettimeofday(&tv_start, NULL); /* current run */ + run_diff_us = timeval_diff(&tv_start, &last_run); /* TODO: do we need `run_diff_us` at all? */ + last_run = tv_start; /* for the next cycle */ + stats_rate_min_max(&rtpe_rate_graphite_min_max, &rtpe_stats_rate); + if (!first_run) /* `stats_counters_calc_rate()` shouldn't be called on the very first cycle */ + stats_counters_calc_rate(&rtpe_stats, run_diff_us, &rtpe_stats_intv, &rtpe_stats_rate); + thread_cancel_enable(); usleep(1000000); /* sleep for 1 second in each iteration */ thread_cancel_disable(); + + first_run = false; } } diff --git a/include/statistics.h b/include/statistics.h index 38485b318..2a109c13b 100644 --- a/include/statistics.h +++ b/include/statistics.h @@ -183,6 +183,7 @@ extern struct global_sampled_min_max rtpe_sampled_min_max; // master lifetime m extern struct global_stats_counter rtpe_stats; // total, cumulative, master extern struct global_stats_counter rtpe_stats_rate; // per-second, calculated once per timer run +extern struct global_stats_counter rtpe_stats_intv; // per-second, calculated once per timer run #define RTPE_STATS_ADD(field, num) atomic64_add(&rtpe_stats.field, num) #define RTPE_STATS_INC(field) RTPE_STATS_ADD(field, 1) @@ -199,6 +200,10 @@ void statistics_free_metrics(GQueue **); const char *statistics_ng(bencode_item_t *input, bencode_item_t *output); void call_rate_stats_updater(void * dummy); +/** + * Calculation of the call rate counters. + * If used with the `stats_rate_min_max()` must only be called in advance, so before that. + */ INLINE void stats_counters_calc_rate(const struct global_stats_counter *stats, long long run_diff_us, struct global_stats_counter *intv, struct global_stats_counter *rate) { @@ -219,7 +224,10 @@ INLINE void stats_counters_calc_diff(const struct global_stats_counter *stats, #undef FA } -// update the running min/max counter `mm` with the newly calculated per-sec rate values `inp` +/** + * Update the running min/max counter `mm` with the newly calculated per-sec rate values `inp`. + * If used with the `stats_counters_calc_rate()`, it must be called only after that. + */ INLINE void stats_rate_min_max(struct global_rate_min_max *mm, struct global_stats_counter *inp) { #define F(x) \ atomic64_mina(&mm->min.x, &inp->x); \ diff --git a/t/test-mix-buffer.c b/t/test-mix-buffer.c index 7ee2e42e6..b978a7d3a 100644 --- a/t/test-mix-buffer.c +++ b/t/test-mix-buffer.c @@ -10,6 +10,7 @@ struct global_stats_gauge rtpe_stats_gauge; struct global_gauge_min_max rtpe_gauge_min_max; struct global_stats_counter rtpe_stats; struct global_stats_counter rtpe_stats_rate; +struct global_stats_counter rtpe_stats_intv; struct global_stats_sampled rtpe_stats_sampled; struct global_sampled_min_max rtpe_sampled_min_max; struct global_sampled_min_max rtpe_sampled_graphite_min_max; diff --git a/t/test-payload-tracker.c b/t/test-payload-tracker.c index 81c4b3c86..6767a1c54 100644 --- a/t/test-payload-tracker.c +++ b/t/test-payload-tracker.c @@ -10,6 +10,7 @@ struct global_stats_gauge rtpe_stats_gauge; struct global_gauge_min_max rtpe_gauge_min_max; struct global_stats_counter rtpe_stats; struct global_stats_counter rtpe_stats_rate; +struct global_stats_counter rtpe_stats_intv; struct global_stats_sampled rtpe_stats_sampled; struct global_sampled_min_max rtpe_sampled_min_max; struct global_sampled_min_max rtpe_sampled_graphite_min_max; diff --git a/t/test-stats.c b/t/test-stats.c index 70c9f47bc..dbe9f8fc7 100644 --- a/t/test-stats.c +++ b/t/test-stats.c @@ -3231,20 +3231,23 @@ int main(void) { // test cmd_ps_min/max/avg call_timer(NULL); + stats_counters_calc_rate(&rtpe_stats, 150000000, &rtpe_stats_intv, &rtpe_stats_rate); stats_rate_min_max(&rtpe_rate_graphite_min_max, &rtpe_stats_rate); - RTPE_STATS_ADD(ng_commands[NGC_OFFER], 100); + RTPE_STATS_ADD(ng_commands[NGC_OFFER], 100); rtpe_now.tv_sec += 2; - RTPE_STATS_ADD(ng_commands[NGC_OFFER], 20); + call_timer(NULL); + stats_counters_calc_rate(&rtpe_stats, 2000000, &rtpe_stats_intv, &rtpe_stats_rate); stats_rate_min_max(&rtpe_rate_graphite_min_max, &rtpe_stats_rate); // timer run time interval increased rtpe_now.tv_sec += 5; - RTPE_STATS_ADD(ng_commands[NGC_OFFER], 200); + call_timer(NULL); + stats_counters_calc_rate(&rtpe_stats, 5000000, &rtpe_stats_intv, &rtpe_stats_rate); stats_rate_min_max(&rtpe_rate_graphite_min_max, &rtpe_stats_rate); graph_str = print_graphite_data();