Skip to content

timers: use Maps for internal duration pooling #11040

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 15 additions & 15 deletions lib/timers.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,14 @@ const TIMEOUT_MAX = 2147483647; // 2^31-1
// operations as close to constant-time as possible.
// (So that performance is not impacted by the number of scheduled timers.)
//
// Object maps are kept which contain linked lists keyed by their duration in
// Maps are kept which contain linked lists keyed by their duration in
// milliseconds.
// The linked lists within also have some meta-properties, one of which is a
// TimerWrap C++ handle, which makes the call after the duration to process the
// list it is attached to.
//
//
// ╔════ > Object Map
// ╔════ > Map
// ║
// ╠══
// ║ refedLists: { '40': { }, '320': { etc } } (keys of millisecond duration)
Expand Down Expand Up @@ -85,18 +85,17 @@ const TIMEOUT_MAX = 2147483647; // 2^31-1
// other alternative timers architectures.


// Object maps containing linked lists of timers, keyed and sorted by their
// Maps containing linked lists of timers, keyed and sorted by their
// duration in milliseconds.
//
// The difference between these two objects is that the former contains timers
// The difference between these two Maps is that the former contains timers
// that will keep the process open if they are the only thing left, while the
// latter will not.
//
// - key = time in milliseconds
// - value = linked list
const refedLists = Object.create(null);
const unrefedLists = Object.create(null);

const refedLists = new Map();
const unrefedLists = new Map();

// Schedule or re-schedule a timer.
// The item must have been enroll()'d first.
Expand Down Expand Up @@ -125,10 +124,11 @@ function insert(item, unrefed) {
const lists = unrefed === true ? unrefedLists : refedLists;

// Use an existing list if there is one, otherwise we need to make a new one.
var list = lists[msecs];
var list = lists.get(msecs);
if (!list) {
debug('no %d list was found in insert, creating a new one', msecs);
lists[msecs] = list = createTimersList(msecs, unrefed);
list = createTimersList(msecs, unrefed);
lists.set(msecs, list);
}

L.append(list, item);
Expand Down Expand Up @@ -220,10 +220,10 @@ function listOnTimeout() {
// Either refedLists[msecs] or unrefedLists[msecs] may have been removed and
// recreated since the reference to `list` was created. Make sure they're
// the same instance of the list before destroying.
if (list._unrefed === true && list === unrefedLists[msecs]) {
delete unrefedLists[msecs];
} else if (list === refedLists[msecs]) {
delete refedLists[msecs];
if (list._unrefed === true && list === unrefedLists.get(msecs)) {
unrefedLists.delete(msecs);
} else if (list === refedLists.get(msecs)) {
refedLists.delete(msecs);
}
}

Expand Down Expand Up @@ -265,12 +265,12 @@ function listOnTimeoutNT(list) {
function reuse(item) {
L.remove(item);

var list = refedLists[item._idleTimeout];
var list = refedLists.get(item._idleTimeout);
// if empty - reuse the watcher
if (list && L.isEmpty(list)) {
debug('reuse hit');
list._timer.stop();
delete refedLists[item._idleTimeout];
refedLists.delete(item._idleTimeout);
return list._timer;
}

Expand Down