Handling of timers with bias.

Timers that don't require maximum precision (most of them, actually) can be
triggered earlier or later within the bias interval.

To reduce wakeups by timers, the expire function now triggers not only all
timers that fall within the elapsed time, but also those whose bias falls
within this interval.
This commit is contained in:
Valentin Bartenev
2018-10-22 16:04:16 +03:00
parent b20e995e80
commit da0ef366dc
5 changed files with 30 additions and 23 deletions

View File

@@ -175,7 +175,7 @@ struct nxt_conn_s {
do { \ do { \
(ev)->work_queue = (wq); \ (ev)->work_queue = (wq); \
(ev)->log = &(c)->log; \ (ev)->log = &(c)->log; \
(ev)->precision = NXT_TIMER_DEFAULT_PRECISION; \ (ev)->bias = NXT_TIMER_DEFAULT_BIAS; \
} while (0) } while (0)

View File

@@ -192,7 +192,7 @@ nxt_http_app_request(nxt_task_t *task, void *obj, void *data)
ar->timer.task = &engine->task; ar->timer.task = &engine->task;
ar->timer.work_queue = &engine->fast_work_queue; ar->timer.work_queue = &engine->fast_work_queue;
ar->timer.log = engine->task.log; ar->timer.log = engine->task.log;
ar->timer.precision = NXT_TIMER_DEFAULT_PRECISION; ar->timer.bias = NXT_TIMER_DEFAULT_BIAS;
ar->r.remote.start = nxt_sockaddr_address(r->remote); ar->r.remote.start = nxt_sockaddr_address(r->remote);
ar->r.remote.length = r->remote->address_length; ar->r.remote.length = r->remote->address_length;

View File

@@ -1578,7 +1578,7 @@ nxt_router_conf_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
app_joint->use_count = 1; app_joint->use_count = 1;
app_joint->app = app; app_joint->app = app;
app_joint->idle_timer.precision = NXT_TIMER_DEFAULT_PRECISION; app_joint->idle_timer.bias = NXT_TIMER_DEFAULT_BIAS;
app_joint->idle_timer.work_queue = &engine->fast_work_queue; app_joint->idle_timer.work_queue = &engine->fast_work_queue;
app_joint->idle_timer.handler = nxt_router_app_idle_timeout; app_joint->idle_timer.handler = nxt_router_app_idle_timeout;
app_joint->idle_timer.task = &engine->task; app_joint->idle_timer.task = &engine->task;
@@ -4119,7 +4119,7 @@ nxt_router_adjust_idle_timer(nxt_task_t *task, void *obj, void *data)
nxt_assert(app->engine == engine); nxt_assert(app->engine == engine);
threshold = engine->timers.now + app->joint->idle_timer.precision; threshold = engine->timers.now + app->joint->idle_timer.bias;
timeout = 0; timeout = 0;
nxt_thread_mutex_lock(&app->mutex); nxt_thread_mutex_lock(&app->mutex);

View File

@@ -75,7 +75,8 @@ nxt_timer_add(nxt_event_engine_t *engine, nxt_timer_t *timer,
time = engine->timers.now + timeout; time = engine->timers.now + timeout;
nxt_debug(timer->task, "timer add: %M %M:%M", timer->time, timeout, time); nxt_debug(timer->task, "timer add: %M±%d %M:%M",
timer->time, timer->bias, timeout, time);
timer->enabled = 1; timer->enabled = 1;
@@ -84,11 +85,12 @@ nxt_timer_add(nxt_event_engine_t *engine, nxt_timer_t *timer,
diff = nxt_msec_diff(time, timer->time); diff = nxt_msec_diff(time, timer->time);
/* /*
* Use the previous timer if difference between it and the * Use the previous timer if difference between it and the
* new timer is less than required precision milliseconds: this * new timer is within bias: this decreases number of rbtree
* decreases number of rbtree operations for fast connections. * operations for fast connections.
*/ */
if (nxt_abs(diff) < timer->precision) { if (nxt_abs(diff) <= timer->bias) {
nxt_debug(timer->task, "timer previous: %M", time); nxt_debug(timer->task, "timer previous: %M±%d",
time, timer->bias);
nxt_timer_change(engine, timer, NXT_TIMER_NOPE, 0); nxt_timer_change(engine, timer, NXT_TIMER_NOPE, 0);
return; return;
@@ -102,7 +104,8 @@ nxt_timer_add(nxt_event_engine_t *engine, nxt_timer_t *timer,
nxt_bool_t nxt_bool_t
nxt_timer_delete(nxt_event_engine_t *engine, nxt_timer_t *timer) nxt_timer_delete(nxt_event_engine_t *engine, nxt_timer_t *timer)
{ {
nxt_debug(timer->task, "timer delete: %M", timer->time); nxt_debug(timer->task, "timer delete: %M±%d",
timer->time, timer->bias);
timer->enabled = 0; timer->enabled = 0;
@@ -142,7 +145,8 @@ nxt_timer_change(nxt_event_engine_t *engine, nxt_timer_t *timer,
timer->change = timers->nchanges; timer->change = timers->nchanges;
} }
nxt_debug(timer->task, "timer change: %M:%d", time, change); nxt_debug(timer->task, "timer change: %M±%d:%d",
time, timer->bias, change);
ch = &timers->changes[timer->change - 1]; ch = &timers->changes[timer->change - 1];
@@ -190,7 +194,8 @@ nxt_timer_changes_commit(nxt_event_engine_t *engine)
/* Fall through. */ /* Fall through. */
case NXT_TIMER_DELETE: case NXT_TIMER_DELETE:
nxt_debug(timer->task, "timer rbtree delete: %M", timer->time); nxt_debug(timer->task, "timer rbtree delete: %M±%d",
timer->time, timer->bias);
nxt_rbtree_delete(&timers->tree, &timer->node); nxt_rbtree_delete(&timers->tree, &timer->node);
nxt_timer_in_tree_clear(timer); nxt_timer_in_tree_clear(timer);
@@ -206,7 +211,8 @@ nxt_timer_changes_commit(nxt_event_engine_t *engine)
while (add < add_end) { while (add < add_end) {
timer = *add; timer = *add;
nxt_debug(timer->task, "timer rbtree insert: %M", timer->time); nxt_debug(timer->task, "timer rbtree insert: %M±%d",
timer->time, timer->bias);
nxt_rbtree_insert(&timers->tree, &timer->node); nxt_rbtree_insert(&timers->tree, &timer->node);
nxt_timer_in_tree_set(timer); nxt_timer_in_tree_set(timer);
@@ -252,10 +258,10 @@ nxt_timer_find(nxt_event_engine_t *engine)
if (timer->enabled) { if (timer->enabled) {
time = timer->time; time = timer->time;
timers->minimum = time; timers->minimum = time - timer->bias;
nxt_debug(timer->task, "timer found minimum: %M:%M", nxt_debug(timer->task, "timer found minimum: %M±%d:%M",
time, timers->now); time, timer->bias, timers->now);
delta = nxt_msec_diff(time, timers->now); delta = nxt_msec_diff(time, timers->now);
@@ -297,14 +303,15 @@ nxt_timer_expire(nxt_event_engine_t *engine, nxt_msec_t now)
{ {
timer = (nxt_timer_t *) node; timer = (nxt_timer_t *) node;
/* timer->time > now */ /* timer->time > now + timer->bias */
if (nxt_msec_diff(timer->time , now) > 0) { if (nxt_msec_diff(timer->time , now) > (int32_t) timer->bias) {
return; return;
} }
next = nxt_rbtree_node_successor(tree, node); next = nxt_rbtree_node_successor(tree, node);
nxt_debug(timer->task, "timer expire delete: %M", timer->time); nxt_debug(timer->task, "timer expire delete: %M±%d",
timer->time, timer->bias);
nxt_rbtree_delete(tree, &timer->node); nxt_rbtree_delete(tree, &timer->node);
nxt_timer_in_tree_clear(timer); nxt_timer_in_tree_clear(timer);

View File

@@ -8,9 +8,9 @@
#define _NXT_TIMER_H_INCLUDED_ #define _NXT_TIMER_H_INCLUDED_
/* Valid values are between 1ms to 255ms. */ /* Valid values are between 0ms to 255ms. */
#define NXT_TIMER_DEFAULT_PRECISION 100 #define NXT_TIMER_DEFAULT_BIAS 50
//#define NXT_TIMER_DEFAULT_PRECISION 1 //#define NXT_TIMER_DEFAULT_BIAS 0
/* /*
@@ -25,7 +25,7 @@ typedef struct {
/* The rbtree node must be the first field. */ /* The rbtree node must be the first field. */
NXT_RBTREE_NODE (node); NXT_RBTREE_NODE (node);
uint8_t precision; uint8_t bias;
uint16_t change:14; uint16_t change:14;
uint16_t enabled:1; uint16_t enabled:1;