Skip to content

Commit 4673aca

Browse files
author
Sun Yu
committed
algorithm improvement
1 parent 671d204 commit 4673aca

File tree

1 file changed

+15
-39
lines changed

1 file changed

+15
-39
lines changed

timeout.c

Lines changed: 15 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -305,24 +305,18 @@ TIMEOUT_PUBLIC void timeouts_del(struct timeouts *T, struct timeout *to) {
305305
} /* timeouts_del() */
306306

307307

308-
static inline reltime_t timeout_rem(struct timeouts *T, struct timeout *to) {
309-
return to->expires - T->curtime;
310-
} /* timeout_rem() */
311-
312-
313-
static inline int timeout_wheel(timeout_t timeout) {
314-
/* must be called with timeout != 0, so fls input is nonzero */
315-
return (fls(MIN(timeout, TIMEOUT_MAX)) - 1) / WHEEL_BIT;
308+
static inline int timeout_wheel(timeout_t curtime, timeout_t expires) {
309+
/* must be called with expires > curtime, so fls input is nonzero */
310+
return (fls(MIN(curtime ^ expires, TIMEOUT_MAX)) - 1) / WHEEL_BIT;
316311
} /* timeout_wheel() */
317312

318313

319314
static inline int timeout_slot(int wheel, timeout_t expires) {
320-
return WHEEL_MASK & ((expires >> (wheel * WHEEL_BIT)) - !!wheel);
315+
return WHEEL_MASK & ((expires >> (wheel * WHEEL_BIT)));
321316
} /* timeout_slot() */
322317

323318

324319
static void timeouts_sched(struct timeouts *T, struct timeout *to, timeout_t expires) {
325-
timeout_t rem;
326320
int wheel, slot;
327321

328322
timeouts_del(T, to);
@@ -332,14 +326,7 @@ static void timeouts_sched(struct timeouts *T, struct timeout *to, timeout_t exp
332326
TO_SET_TIMEOUTS(to, T);
333327

334328
if (expires > T->curtime) {
335-
rem = timeout_rem(T, to);
336-
337-
/* rem is nonzero since:
338-
* rem == timeout_rem(T,to),
339-
* == to->expires - T->curtime
340-
* and above we have expires > T->curtime.
341-
*/
342-
wheel = timeout_wheel(rem);
329+
wheel = timeout_wheel(T->curtime, expires);
343330
slot = timeout_slot(wheel, to->expires);
344331

345332
to->pending = &T->wheel[wheel][slot];
@@ -402,34 +389,26 @@ TIMEOUT_PUBLIC void timeouts_update(struct timeouts *T, abstime_t curtime) {
402389
/*
403390
* Calculate the slots expiring in this wheel
404391
*
405-
* If the elapsed time is greater than the maximum period of
392+
* Assume that current slot is empty, it's timer either expired or moved to the lower wheel.
393+
* If the elapsed time is greater or equal to the maximum period of
406394
* the wheel, mark every position as expiring.
407395
*
408396
* Otherwise, to determine the expired slots fill in all the
409397
* bits between the last slot processed and the current
410-
* slot, inclusive of the last slot. We'll bitwise-AND this
398+
* slot(exclusive, we don't need to check it again), inclusive of the last slot. We'll bitwise-AND this
411399
* with our pending set below.
412-
*
413-
* If a wheel rolls over, force a tick of the next higher
414-
* wheel.
415400
*/
416-
if ((elapsed >> (wheel * WHEEL_BIT)) > WHEEL_MAX) {
401+
if ((elapsed >> (wheel * WHEEL_BIT)) >= WHEEL_MAX) {
417402
pending = (wheel_t)~WHEEL_C(0);
418403
} else {
419-
wheel_t _elapsed = WHEEL_MASK & (elapsed >> (wheel * WHEEL_BIT));
404+
wheel_t _elapsed;
420405
int oslot, nslot;
421406

422-
/*
423-
* TODO: It's likely that at least one of the
424-
* following three bit fill operations is redundant
425-
* or can be replaced with a simpler operation.
426-
*/
427407
oslot = WHEEL_MASK & (T->curtime >> (wheel * WHEEL_BIT));
428-
pending = rotl(((UINT64_C(1) << _elapsed) - 1), oslot);
429-
430408
nslot = WHEEL_MASK & (curtime >> (wheel * WHEEL_BIT));
431-
pending |= rotr(rotl(((WHEEL_C(1) << _elapsed) - 1), nslot), _elapsed);
432-
pending |= WHEEL_C(1) << nslot;
409+
_elapsed = WHEEL_MASK & (WHEEL_LEN + nslot - oslot);
410+
411+
pending = rotr(rotl(((WHEEL_C(1) << _elapsed) - 1), nslot + 1), _elapsed);
433412
}
434413

435414
while (pending & T->pending[wheel]) {
@@ -441,9 +420,6 @@ TIMEOUT_PUBLIC void timeouts_update(struct timeouts *T, abstime_t curtime) {
441420

442421
if (!(0x1 & pending))
443422
break; /* break if we didn't wrap around end of wheel */
444-
445-
/* if we're continuing, the next wheel must tick at least once */
446-
elapsed = MAX(elapsed, (WHEEL_LEN << (wheel * WHEEL_BIT)));
447423
}
448424

449425
T->curtime = curtime;
@@ -512,8 +488,8 @@ static timeout_t timeouts_int(struct timeouts *T) {
512488

513489
/* ctz input cannot be zero: T->pending[wheel] is
514490
* nonzero, so rotr() is nonzero. */
515-
_timeout = (ctz(rotr(T->pending[wheel], slot)) + !!wheel) << (wheel * WHEEL_BIT);
516-
/* +1 to higher order wheels as those timeouts are one rotation in the future (otherwise they'd be on a lower wheel or expired) */
491+
_timeout = (ctz(rotr(T->pending[wheel], slot)) + !!(T->pending[wheel] & (TIMEOUT_C(1) << slot))) << (wheel * WHEEL_BIT);
492+
/* +1 when a timeout greater than TIMEOUT_MAX and wrap in to current slot of the highest wheel */
517493

518494
_timeout -= relmask & T->curtime;
519495
/* reduce by how much lower wheels have progressed */

0 commit comments

Comments
 (0)