From 5ecc4a951612f5e7dc636c10545587a14d1d4843 Mon Sep 17 00:00:00 2001 From: Anatoli Papirovski Date: Wed, 29 Nov 2017 12:46:13 -0500 Subject: [PATCH 1/2] timers: improvements to TimersList management No longer use delete to remove keys on unrefed & refed lists, instead simply set to undefined. Move all the TimersList instantiation code into the constructor. Compare values to undefined & null as appropriate instead of truthy or falsy. --- lib/timers.js | 41 +++++++++++++++++------------------------ 1 file changed, 17 insertions(+), 24 deletions(-) diff --git a/lib/timers.js b/lib/timers.js index d0828669d77183..d0077e6e8e1e6a 100644 --- a/lib/timers.js +++ b/lib/timers.js @@ -55,7 +55,7 @@ const activateImmediateCheck = process._activateImmediateCheck; delete process._activateImmediateCheck; // Timeout values > TIMEOUT_MAX are set to 1. -const TIMEOUT_MAX = 2147483647; // 2^31-1 +const TIMEOUT_MAX = 2 ** 31 - 1; // HOW and WHY the timers implementation works the way it does. @@ -173,9 +173,9 @@ function insert(item, unrefed) { // Use an existing list if there is one, otherwise we need to make a new one. var list = lists[msecs]; - if (!list) { + if (list === undefined) { debug('no %d list was found in insert, creating a new one', msecs); - lists[msecs] = list = createTimersList(msecs, unrefed); + lists[msecs] = list = new TimersList(msecs, unrefed); } if (!item[async_id_symbol] || item._destroyed) { @@ -194,28 +194,21 @@ function insert(item, unrefed) { assert(!L.isEmpty(list)); // list is not empty } -function createTimersList(msecs, unrefed) { - // Make a new linked list of timers, and create a TimerWrap to schedule - // processing for the list. - const list = new TimersList(msecs, unrefed); - L.init(list); - list._timer._list = list; - - if (unrefed === true) list._timer.unref(); - list._timer.start(msecs); - - list._timer[kOnTimeout] = listOnTimeout; - - return list; -} - function TimersList(msecs, unrefed) { - this._idleNext = null; // Create the list with the linkedlist properties to - this._idlePrev = null; // prevent any unnecessary hidden class changes. - this._timer = new TimerWrap(); + this._idleNext = this; // Create the list with the linkedlist properties to + this._idlePrev = this; // prevent any unnecessary hidden class changes. this._unrefed = unrefed; this.msecs = msecs; this.nextTick = false; + + const timer = this._timer = new TimerWrap(); + timer._list = this; + + if (unrefed === true) + timer.unref(); + timer.start(msecs); + + timer[kOnTimeout] = listOnTimeout; } function listOnTimeout() { @@ -359,7 +352,7 @@ function reuse(item) { var list = refedLists[item._idleTimeout]; // if empty - reuse the watcher - if (list && L.isEmpty(list)) { + if (list !== undefined && L.isEmpty(list)) { debug('reuse hit'); list._timer.stop(); delete refedLists[item._idleTimeout]; @@ -382,7 +375,7 @@ const unenroll = exports.unenroll = function(item) { } var handle = reuse(item); - if (handle) { + if (handle !== null) { debug('unenroll: list empty'); handle.close(); } @@ -610,7 +603,7 @@ Timeout.prototype.unref = function() { } var handle = reuse(this); - if (handle) { + if (handle !== null) { handle._list = undefined; } From 253341a2aafa6f7f10521fe25348986bec079c9d Mon Sep 17 00:00:00 2001 From: Anatoli Papirovski Date: Thu, 30 Nov 2017 09:03:23 -0500 Subject: [PATCH 2/2] timers: compare to null not falsey --- lib/timers.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/timers.js b/lib/timers.js index d0077e6e8e1e6a..c9202cc0908bb9 100644 --- a/lib/timers.js +++ b/lib/timers.js @@ -652,7 +652,7 @@ function ImmediateList() { // Appends an item to the end of the linked list, adjusting the current tail's // previous and next pointers where applicable ImmediateList.prototype.append = function(item) { - if (this.tail) { + if (this.tail !== null) { this.tail._idleNext = item; item._idlePrev = this.tail; } else { @@ -664,11 +664,11 @@ ImmediateList.prototype.append = function(item) { // Removes an item from the linked list, adjusting the pointers of adjacent // items and the linked list's head or tail pointers as necessary ImmediateList.prototype.remove = function(item) { - if (item._idleNext) { + if (item._idleNext !== null) { item._idleNext._idlePrev = item._idlePrev; } - if (item._idlePrev) { + if (item._idlePrev !== null) { item._idlePrev._idleNext = item._idleNext; } @@ -694,7 +694,7 @@ function processImmediate() { // immediate callbacks are executed immediateQueue.head = immediateQueue.tail = null; - while (immediate) { + while (immediate !== null) { domain = immediate.domain; if (!immediate._onImmediate) { @@ -715,7 +715,7 @@ function processImmediate() { // If `clearImmediate(immediate)` wasn't called from the callback, use the // `immediate`'s next item - if (immediate._idleNext) + if (immediate._idleNext !== null) immediate = immediate._idleNext; else immediate = next; @@ -747,11 +747,11 @@ function tryOnImmediate(immediate, oldTail) { } } - if (threw && immediate._idleNext) { + if (threw && immediate._idleNext !== null) { // Handle any remaining on next tick, assuming we're still alive to do so. const curHead = immediateQueue.head; const next = immediate._idleNext; - if (curHead) { + if (curHead !== null) { curHead._idlePrev = oldTail; oldTail._idleNext = curHead; next._idlePrev = null;