Skip to content

Commit 83330a0

Browse files
apapirovskiBridgeAR
authored andcommitted
timers: do less work in insert
Most of the code in insert is only applicable to scheduling non-timers or re-scheduling timers. We can skip most of it in the case of setTimeout, setInterval & setUnrefTimeout. PR-URL: #27345 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Jeremiah Senkpiel <[email protected]> Reviewed-By: Rich Trott <[email protected]> Reviewed-By: James M Snell <[email protected]>
1 parent 7b2bf20 commit 83330a0

File tree

2 files changed

+39
-33
lines changed

2 files changed

+39
-33
lines changed

lib/internal/timers.js

+31-27
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ function initAsyncResource(resource, type) {
155155

156156
// Timer constructor function.
157157
// The entire prototype is defined in lib/timers.js
158-
function Timeout(callback, after, args, isRepeat) {
158+
function Timeout(callback, after, args, isRepeat, isRefed) {
159159
after *= 1; // Coalesce to number or NaN
160160
if (!(after >= 1 && after <= TIMEOUT_MAX)) {
161161
if (after > TIMEOUT_MAX) {
@@ -179,7 +179,9 @@ function Timeout(callback, after, args, isRepeat) {
179179
this._repeat = isRepeat ? after : null;
180180
this._destroyed = false;
181181

182-
this[kRefed] = null;
182+
if (isRefed)
183+
incRefCount();
184+
this[kRefed] = isRefed;
183185

184186
initAsyncResource(this, 'Timeout');
185187
}
@@ -295,27 +297,43 @@ function decRefCount() {
295297
// Schedule or re-schedule a timer.
296298
// The item must have been enroll()'d first.
297299
function active(item) {
298-
insert(item, true, getLibuvNow());
300+
insertGuarded(item, true);
299301
}
300302

301303
// Internal APIs that need timeouts should use `unrefActive()` instead of
302304
// `active()` so that they do not unnecessarily keep the process open.
303305
function unrefActive(item) {
304-
insert(item, false, getLibuvNow());
306+
insertGuarded(item, false);
305307
}
306308

307309
// The underlying logic for scheduling or re-scheduling a timer.
308310
//
309311
// Appends a timer onto the end of an existing timers list, or creates a new
310312
// list if one does not already exist for the specified timeout duration.
311-
function insert(item, refed, start) {
312-
let msecs = item._idleTimeout;
313+
function insertGuarded(item, refed, start) {
314+
const msecs = item._idleTimeout;
313315
if (msecs < 0 || msecs === undefined)
314316
return;
315317

316-
// Truncate so that accuracy of sub-millisecond timers is not assumed.
317-
msecs = MathTrunc(msecs);
318+
insert(item, msecs, start);
319+
320+
if (!item[async_id_symbol] || item._destroyed) {
321+
item._destroyed = false;
322+
initAsyncResource(item, 'Timeout');
323+
}
324+
325+
if (refed === !item[kRefed]) {
326+
if (refed)
327+
incRefCount();
328+
else
329+
decRefCount();
330+
}
331+
item[kRefed] = refed;
332+
}
318333

334+
function insert(item, msecs, start = getLibuvNow()) {
335+
// Truncate so that accuracy of sub-milisecond timers is not assumed.
336+
msecs = MathTrunc(msecs);
319337
item._idleStart = start;
320338

321339
// Use an existing list if there is one, otherwise we need to make a new one.
@@ -332,19 +350,6 @@ function insert(item, refed, start) {
332350
}
333351
}
334352

335-
if (!item[async_id_symbol] || item._destroyed) {
336-
item._destroyed = false;
337-
initAsyncResource(item, 'Timeout');
338-
}
339-
340-
if (refed === !item[kRefed]) {
341-
if (refed)
342-
incRefCount();
343-
else
344-
decRefCount();
345-
}
346-
item[kRefed] = refed;
347-
348353
L.append(list, item);
349354
}
350355

@@ -354,8 +359,8 @@ function setUnrefTimeout(callback, after) {
354359
throw new ERR_INVALID_CALLBACK(callback);
355360
}
356361

357-
const timer = new Timeout(callback, after, undefined, false);
358-
unrefActive(timer);
362+
const timer = new Timeout(callback, after, undefined, false, false);
363+
insert(timer, timer._idleTimeout);
359364

360365
return timer;
361366
}
@@ -540,16 +545,14 @@ function getTimerCallbacks(runNextTicks) {
540545
} finally {
541546
if (timer._repeat && timer._idleTimeout !== -1) {
542547
timer._idleTimeout = timer._repeat;
543-
if (start === undefined)
544-
start = getLibuvNow();
545-
insert(timer, timer[kRefed], start);
548+
insert(timer, timer._idleTimeout, start);
546549
} else if (!timer._idleNext && !timer._idlePrev) {
547550
if (timer[kRefed])
548551
refCount--;
549552
timer[kRefed] = null;
550553

551554
if (destroyHooksExist() && !timer._destroyed) {
552-
emitDestroy(timer[async_id_symbol]);
555+
emitDestroy(asyncId);
553556
}
554557
timer._destroyed = true;
555558
}
@@ -598,6 +601,7 @@ module.exports = {
598601
},
599602
active,
600603
unrefActive,
604+
insert,
601605
timerListMap,
602606
timerListQueue,
603607
decRefCount,

lib/timers.js

+8-6
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@ const {
4646
timerListQueue,
4747
immediateQueue,
4848
active,
49-
unrefActive
49+
unrefActive,
50+
insert
5051
} = require('internal/timers');
5152
const {
5253
promisify: { custom: customPromisify },
@@ -142,16 +143,17 @@ function setTimeout(callback, after, arg1, arg2, arg3) {
142143
break;
143144
}
144145

145-
const timeout = new Timeout(callback, after, args, false);
146-
active(timeout);
146+
const timeout = new Timeout(callback, after, args, false, true);
147+
insert(timeout, timeout._idleTimeout);
147148

148149
return timeout;
149150
}
150151

151152
setTimeout[customPromisify] = function(after, value) {
152153
const args = value !== undefined ? [value] : value;
153154
return new Promise((resolve) => {
154-
active(new Timeout(resolve, after, args, false));
155+
const timeout = new Timeout(resolve, after, args, false, true);
156+
insert(timeout, timeout._idleTimeout);
155157
});
156158
};
157159

@@ -188,8 +190,8 @@ function setInterval(callback, repeat, arg1, arg2, arg3) {
188190
break;
189191
}
190192

191-
const timeout = new Timeout(callback, repeat, args, true);
192-
active(timeout);
193+
const timeout = new Timeout(callback, repeat, args, true, true);
194+
insert(timeout, timeout._idleTimeout);
193195

194196
return timeout;
195197
}

0 commit comments

Comments
 (0)