Skip to content

Commit

Permalink
process: use linked reusable queue for ticks
Browse files Browse the repository at this point in the history
PR-URL: #18617
Reviewed-By: Anna Henningsen <[email protected]>
Reviewed-By: Benjamin Gruenbaum <[email protected]>
Reviewed-By: Ruben Bridgewater <[email protected]>
Reviewed-By: Anatoli Papirovski <[email protected]>
Reviewed-By: Benedikt Meurer <[email protected]>
Reviewed-By: Matteo Collina <[email protected]>
Reviewed-By: Luigi Pinca <[email protected]>
Reviewed-By: Tiancheng "Timothy" Gu <[email protected]>
  • Loading branch information
mafintosh authored and addaleax committed Feb 27, 2018
1 parent 4012ae8 commit cfb78bc
Showing 1 changed file with 49 additions and 27 deletions.
76 changes: 49 additions & 27 deletions lib/internal/process/next_tick.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,32 +32,55 @@ function setupNextTick() {
const kHasScheduled = 0;
const kHasPromiseRejections = 1;

const nextTickQueue = {
head: null,
tail: null,
// Queue size for each tick array. Must be a factor of two.
const kQueueSize = 2048;
const kQueueMask = kQueueSize - 1;

class FixedQueue {
constructor() {
this.bottom = 0;
this.top = 0;
this.list = new Array(kQueueSize);
this.next = null;
}

push(data) {
const entry = { data, next: null };
if (this.tail !== null) {
this.tail.next = entry;
} else {
this.head = entry;
tickInfo[kHasScheduled] = 1;
}
this.tail = entry;
},
this.list[this.top] = data;
this.top = (this.top + 1) & kQueueMask;
}

shift() {
if (this.head === null)
return;
const ret = this.head.data;
if (this.head === this.tail) {
this.head = this.tail = null;
const next = this.list[this.bottom];
if (next === undefined) return null;
this.list[this.bottom] = undefined;
this.bottom = (this.bottom + 1) & kQueueMask;
return next;
}
}

var head = new FixedQueue();
var tail = head;

function push(data) {
if (head.bottom === head.top) {
if (head.list[head.top] !== undefined)
head = head.next = new FixedQueue();
else
tickInfo[kHasScheduled] = 1;
}
head.push(data);
}

function shift() {
const next = tail.shift();
if (tail.top === tail.bottom) {
if (tail.next)
tail = tail.next;
else
tickInfo[kHasScheduled] = 0;
} else {
this.head = this.head.next;
}
return ret;
}
};
return next;
}

process.nextTick = nextTick;
// Needs to be accessible from beyond this scope.
Expand All @@ -69,7 +92,7 @@ function setupNextTick() {
function _tickCallback() {
let tock;
do {
while (tock = nextTickQueue.shift()) {
while (tock = shift()) {
const asyncId = tock[async_id_symbol];
emitBefore(asyncId, tock[trigger_async_id_symbol]);
// emitDestroy() places the async_id_symbol into an asynchronous queue
Expand All @@ -93,7 +116,7 @@ function setupNextTick() {
emitAfter(asyncId);
}
runMicrotasks();
} while (nextTickQueue.head !== null || emitPromiseRejectionWarnings());
} while (head.top !== head.bottom || emitPromiseRejectionWarnings());
tickInfo[kHasPromiseRejections] = 0;
}

Expand Down Expand Up @@ -139,8 +162,7 @@ function setupNextTick() {
args[i - 1] = arguments[i];
}

nextTickQueue.push(new TickObject(callback, args,
getDefaultTriggerAsyncId()));
push(new TickObject(callback, args, getDefaultTriggerAsyncId()));
}

// `internalNextTick()` will not enqueue any callback when the process is
Expand Down Expand Up @@ -168,6 +190,6 @@ function setupNextTick() {

if (triggerAsyncId === null)
triggerAsyncId = getDefaultTriggerAsyncId();
nextTickQueue.push(new TickObject(callback, args, triggerAsyncId));
push(new TickObject(callback, args, triggerAsyncId));
}
}

0 comments on commit cfb78bc

Please sign in to comment.