From 87d68080e9c71ee54775a7fa88a6c4632ba520ba Mon Sep 17 00:00:00 2001 From: tom910 Date: Tue, 30 Mar 2021 23:08:07 +0300 Subject: [PATCH] Improve MinHeap implementation Migrated to a new algorithm that does not go beyond the array, thus de-optimization of this piece of code is not happening --- packages/scheduler/src/SchedulerMinHeap.js | 91 +++++++++++----------- 1 file changed, 45 insertions(+), 46 deletions(-) diff --git a/packages/scheduler/src/SchedulerMinHeap.js b/packages/scheduler/src/SchedulerMinHeap.js index 03d82f4df65cc..fecf68a7147c0 100644 --- a/packages/scheduler/src/SchedulerMinHeap.js +++ b/packages/scheduler/src/SchedulerMinHeap.js @@ -20,72 +20,71 @@ export function push(heap: Heap, node: Node): void { } export function peek(heap: Heap): Node | null { - const first = heap[0]; - return first === undefined ? null : first; + return heap.length === 0 ? null : heap[0]; } export function pop(heap: Heap): Node | null { - const first = heap[0]; - if (first !== undefined) { - const last = heap.pop(); - if (last !== first) { - heap[0] = last; - siftDown(heap, last, 0); - } - return first; - } else { + if (heap.length === 0) { return null; } + const first = heap[0]; + + const last = heap.pop(); + + if (last !== first) { + heap[0] = last; + siftDown(heap, last, 0); + } + + return first; } function siftUp(heap, node, i) { let index = i; - while (true) { - const parentIndex = (index - 1) >>> 1; + + while (index > 0) { + const parentIndex = Math.floor((index - 1) / 2); const parent = heap[parentIndex]; - if (parent !== undefined && compare(parent, node) > 0) { - // The parent is larger. Swap positions. - heap[parentIndex] = node; - heap[index] = parent; - index = parentIndex; - } else { - // The parent is smaller. Exit. - return; + + if (compare(parent, node) < 0) { + break; } + swap(heap, parentIndex, index); + index = parentIndex; } } function siftDown(heap, node, i) { let index = i; - const length = heap.length; - while (index < length) { - const leftIndex = (index + 1) * 2 - 1; - const left = heap[leftIndex]; - const rightIndex = leftIndex + 1; - const right = heap[rightIndex]; - - // If the left or right node is smaller, swap with the smaller of those. - if (left !== undefined && compare(left, node) < 0) { - if (right !== undefined && compare(right, left) < 0) { - heap[index] = right; - heap[rightIndex] = node; - index = rightIndex; - } else { - heap[index] = left; - heap[leftIndex] = node; - index = leftIndex; - } - } else if (right !== undefined && compare(right, node) < 0) { - heap[index] = right; - heap[rightIndex] = node; - index = rightIndex; - } else { - // Neither child is smaller. Exit. - return; + const halfLength = Math.floor(heap.length / 2); + + while (index < halfLength) { + let bestIndex = index * 2 + 1; + const rightIndex = index * 2 + 2; + + // If the right node is smaller, swap with the smaller of those. + if ( + heap.length > rightIndex && + compare(heap[rightIndex], heap[bestIndex]) < 0 + ) { + bestIndex = rightIndex; + } + + if (compare(node, heap[bestIndex]) < 0) { + break; } + + swap(heap, bestIndex, index); + index = bestIndex; } } +function swap(heap, left, right) { + const item = heap[left]; + heap[left] = heap[right]; + heap[right] = item; +} + function compare(a, b) { // Compare sort index first, then task id. const diff = a.sortIndex - b.sortIndex;