From 74de4ad659e16db9bb9f41cec0c10a07b0523e63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCrg=C3=BCn=20Day=C4=B1o=C4=9Flu?= Date: Mon, 17 Feb 2025 02:01:11 +0100 Subject: [PATCH 1/3] lib: optimize priority queue --- lib/internal/priority_queue.js | 44 +++++++++++++++++++++------------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/lib/internal/priority_queue.js b/lib/internal/priority_queue.js index e61cc04c101b7c..747c723afff592 100644 --- a/lib/internal/priority_queue.js +++ b/lib/internal/priority_queue.js @@ -47,20 +47,28 @@ module.exports = class PriorityQueue { const setPosition = this.#setPosition; const heap = this.#heap; const size = this.#size; + const hsize = size >> 1; const item = heap[pos]; - while (pos * 2 <= size) { - let childIndex = pos * 2 + 1; - if (childIndex > size || compare(heap[pos * 2], heap[childIndex]) < 0) - childIndex = pos * 2; - const child = heap[childIndex]; - if (compare(item, child) <= 0) - break; + while (pos <= hsize) { + let child = pos << 1; + const nextChild = child + 1; + let childItem = heap[child]; + + if (nextChild <= size && compare(heap[nextChild], childItem) < 0) { + child = nextChild; + childItem = heap[nextChild]; + } + + if (compare(item, childItem) <= 0) break; + if (setPosition !== undefined) - setPosition(child, pos); - heap[pos] = child; - pos = childIndex; + setPosition(childItem, pos); + + heap[pos] = childItem; + pos = child; } + heap[pos] = item; if (setPosition !== undefined) setPosition(item, pos); @@ -73,27 +81,31 @@ module.exports = class PriorityQueue { const item = heap[pos]; while (pos > 1) { - const parent = heap[pos / 2 | 0]; - if (compare(parent, item) <= 0) + const parent = pos >> 1; + const parentItem = heap[parent]; + if (compare(parentItem, item) <= 0) break; - heap[pos] = parent; + heap[pos] = parentItem; if (setPosition !== undefined) - setPosition(parent, pos); - pos = pos / 2 | 0; + setPosition(parentItem, pos); + pos = parent; } + heap[pos] = item; if (setPosition !== undefined) setPosition(item, pos); } removeAt(pos) { + if (pos > this.#size) return; + const heap = this.#heap; const size = --this.#size; heap[pos] = heap[size + 1]; heap[size + 1] = undefined; if (size > 0 && pos <= size) { - if (pos > 1 && this.#compare(heap[pos / 2 | 0], heap[pos]) > 0) + if (pos > 1 && this.#compare(heap[pos >> 1], heap[pos]) > 0) this.percolateUp(pos); else this.percolateDown(pos); From be07d41871b2c00361dddb13d3eb5bb51f564cd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCrg=C3=BCn=20Day=C4=B1o=C4=9Flu?= Date: Mon, 17 Feb 2025 08:29:14 +0100 Subject: [PATCH 2/3] coverage --- test/parallel/test-priority-queue.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/test/parallel/test-priority-queue.js b/test/parallel/test-priority-queue.js index b98d228b08763b..a04d8016a587d7 100644 --- a/test/parallel/test-priority-queue.js +++ b/test/parallel/test-priority-queue.js @@ -102,6 +102,9 @@ const PriorityQueue = require('internal/priority_queue'); // Check that removing the last item doesn't throw queue.removeAt(6); + // Check that removing an item that doesn't exist doesn't throw + queue.removeAt(15); + assert.strictEqual(queue.shift().value, 1); assert.strictEqual(queue.shift().value, 2); assert.strictEqual(queue.shift().value, 2); From db55a715dcde58ce6d87e9cbfd7f980b3e545fd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=BCrg=C3=BCn=20Day=C4=B1o=C4=9Flu?= Date: Sun, 23 Feb 2025 11:57:24 +0100 Subject: [PATCH 3/3] remove breaking change --- lib/internal/priority_queue.js | 9 ++++----- test/parallel/test-priority-queue.js | 3 --- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/lib/internal/priority_queue.js b/lib/internal/priority_queue.js index 747c723afff592..c172e2351c93ab 100644 --- a/lib/internal/priority_queue.js +++ b/lib/internal/priority_queue.js @@ -97,12 +97,11 @@ module.exports = class PriorityQueue { } removeAt(pos) { - if (pos > this.#size) return; - const heap = this.#heap; - const size = --this.#size; - heap[pos] = heap[size + 1]; - heap[size + 1] = undefined; + let size = this.#size; + heap[pos] = heap[size]; + heap[size] = undefined; + size = --this.#size; if (size > 0 && pos <= size) { if (pos > 1 && this.#compare(heap[pos >> 1], heap[pos]) > 0) diff --git a/test/parallel/test-priority-queue.js b/test/parallel/test-priority-queue.js index a04d8016a587d7..b98d228b08763b 100644 --- a/test/parallel/test-priority-queue.js +++ b/test/parallel/test-priority-queue.js @@ -102,9 +102,6 @@ const PriorityQueue = require('internal/priority_queue'); // Check that removing the last item doesn't throw queue.removeAt(6); - // Check that removing an item that doesn't exist doesn't throw - queue.removeAt(15); - assert.strictEqual(queue.shift().value, 1); assert.strictEqual(queue.shift().value, 2); assert.strictEqual(queue.shift().value, 2);