MT#57378 move `stats_counters_calc_rate()` to a separate thread

Similarly as for the `stats_rate_min_max()`,
move the `stats_counters_calc_rate()` functionality
to the same separate thread, so that we do the work
more efficiently and not be dependent on the call_timer
runs by poller.

Furthermore it makes more sense to keep in the `statistics.c`,
since it obviously has to do with statistics.

Additionally:

Update the test-stats due to these changes in the `call_timer()`

We have to call the `stats_counters_calc_rate()` now explicitely from
the test-stats.c, because the `call_timer()` is not anymore
responsible for providing stats counters rate calculations.

Change-Id: I1682eb76e3057f0f431c27b9633717d965313a1a
pull/1675/head
Donat Zenichev 2 years ago
parent 237a3a6402
commit 131702c6e4

@ -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);

@ -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;
}
}

@ -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); \

@ -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;

@ -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;

@ -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();

Loading…
Cancel
Save