Skip to content

Next: Improve performance and bump to v2.7#667

Merged
ignlg merged 18 commits intomasterfrom
next
Sep 30, 2025
Merged

Next: Improve performance and bump to v2.7#667
ignlg merged 18 commits intomasterfrom
next

Conversation

@ignlg
Copy link
Owner

@ignlg ignlg commented Sep 30, 2025

Summary by CodeRabbit

  • Refactor
    • Internal heap algorithms optimized for reduced allocations and faster push/pop/heapify with no API changes.
  • Documentation
    • Added changelog entries for 2.6 and 2.7 and updated “Defined in” source links across docs.
  • Bug Fixes
    • Fixed a malformed Markdown link in the changelog.
  • Tests
    • Added ESLint overrides in tests touching private methods.
  • Chores
    • Bumped package version to 2.7.0.

@ignlg ignlg self-assigned this Sep 30, 2025
@coderabbitai
Copy link

coderabbitai bot commented Sep 30, 2025

Walkthrough

Version bumped to 2.7.0. Internal refactors in Heap and HeapAsync adjust heapify start index, parent index computation, swapping, and sift up/down implementations. Documentation HTML “Defined in” links updated to new commit references and changelog entries added. Tests gain ESLint overrides to allow any. No public API changes.

Changes

Cohort / File(s) Summary
Core heap refactors
src/Heap.ts, src/HeapAsync.ts
Refactor heapify start index and parent-index calculation, replace destructuring swaps with temp-variable swaps, and reimplement _sortNodeDown/_sortNodeUp to use cached values with final assignment; preserve public API.
Docs: type/function pages
docs/functions/toInt.html, docs/types/AsyncComparator.html, docs/types/AsyncIsEqual.html, docs/types/Comparator.html, docs/types/IsEqual.html
Update “Defined in” source links to point at new commit hashes/paths; no content or signature changes.
Docs: index and README
docs/index.html, README.md
Add/reorder changelog entries (2.6, 2.7) and fix a Markdown link in the 2.2 entry.
Versioning
package.json
Bump version 2.6.0 → 2.7.0.
Tests linting
tests/heap-async/heap-async-private-methods.test.ts, tests/heap/heap-private-methods.test.ts
Add file-level ESLint disable for no-explicit-any; no test logic changes.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor Client
  participant Heap as Heap (sync)
  participant Cmp as Comparator

  rect rgb(245,250,255)
  note over Heap: Initialization / heapify (start from parent(last))
  Client->>Heap: new Heap(items, comparator)
  Heap->>Heap: for i = parent(last) downto 0
  Heap->>Heap: _sortNodeDown(i)  -- uses cached value + final assignment
  end

  rect rgb(245,255,245)
  note over Heap: Push
  Client->>Heap: push(value)
  Heap->>Heap: insert at end
  Heap->>Heap: _sortNodeUp(idx)  -- cached value + final assignment
  Heap->>Cmp: compare during ascent
  end

  rect rgb(255,248,240)
  note over Heap: Pop
  Client->>Heap: pop()
  Heap->>Heap: move last to root (temp swap)
  Heap->>Heap: _sortNodeDown(0)
  Heap->>Cmp: compare during descent
  end
Loading
sequenceDiagram
  autonumber
  actor Client
  participant AHeap as HeapAsync
  participant ACmp as AsyncComparator

  note over AHeap: Same control flow as sync, with awaited comparisons
  Client->>AHeap: push/pop/top...
  AHeap->>AHeap: _sortNodeUp/_sortNodeDown (iterative, cached value)
  AHeap->>ACmp: await compare(...)
  ACmp-->>AHeap: Promise<number>
  AHeap-->>Client: result
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Poem

A rabbit adjusts each heap with care,
Shifts a hole here, lifts a node there.
Bitwise hops to parent’s lair,
Docs now point where sources share.
Version ticks—2.7 fair— 🐇✨

Pre-merge checks and finishing touches

❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Title Check ❓ Inconclusive The title correctly highlights the two main changes—performance improvements and the version bump to 2.7—but includes an extraneous “Next:” prefix that does not add value or clarity and may confuse readers about its intent. Consider simplifying the title to focus solely on the changes, for example: “Improve heap performance and bump version to 2.7” to remove the unnecessary prefix and clearly convey the update.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed No functions found in the changes. Docstring coverage check skipped.
✨ Finishing touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch next

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6a14ce5 and 17cf612.

⛔ Files ignored due to path filters (2)
  • dist/heap-js.es5.js is excluded by !**/dist/**
  • dist/heap-js.umd.js is excluded by !**/dist/**
📒 Files selected for processing (6)
  • docs/functions/toInt.html (1 hunks)
  • docs/index.html (2 hunks)
  • docs/types/AsyncComparator.html (1 hunks)
  • docs/types/AsyncIsEqual.html (1 hunks)
  • docs/types/Comparator.html (1 hunks)
  • docs/types/IsEqual.html (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • docs/index.html
🚧 Files skipped from review as they are similar to previous changes (4)
  • docs/types/AsyncComparator.html
  • docs/types/Comparator.html
  • docs/types/AsyncIsEqual.html
  • docs/types/IsEqual.html
🔇 Additional comments (1)
docs/functions/toInt.html (1)

1-1: Generated documentation file - no review needed.

This is a TypeDoc-generated HTML documentation file. The change updates the commit hash in the "Defined in" source link, which is expected when documentation is regenerated. Generated documentation files typically don't require code review.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🧪 Early access (Sonnet 4.5): enabled

We are currently testing the Sonnet 4.5 model, which is expected to improve code review quality. However, this model may lead to increased noise levels in the review comments. Please disable the early access features if the noise level causes any inconvenience.

Note:

  • Public repositories are always opted into early access features.
  • You can enable or disable early access features from the CodeRabbit UI or by updating the CodeRabbit configuration file.

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (2)
docs/types/IsEqual.html (1)

1-1: Repository URL mismatch in generated documentation.

The "Defined in" link references github.com/BeatsuDev/heap-js instead of github.com/ignlg/heap-js (where this PR resides). This is consistent with the same issue in other documentation files and indicates the TypeDoc output was generated from incorrect repository settings.

docs/types/AsyncComparator.html (1)

1-1: Repository URL mismatch in generated documentation.

The "Defined in" link references github.com/BeatsuDev/heap-js instead of the correct github.com/ignlg/heap-js repository. This matches the issue found in the other documentation files.

🧹 Nitpick comments (1)
src/HeapAsync.ts (1)

430-438: Optimize heapify loop start index

In src/HeapAsync.ts’s init, adjust the loop to begin at the parent of the last element rather than at Math.floor(this.heapArray.length / 2), which invokes _sortNodeDown once on a leaf. For example:

- for (let i = Math.floor(this.heapArray.length / 2); i >= 0; --i) {
+ for (let i = Math.floor(this.heapArray.length / 2) - 1; i >= 0; --i) {
    await this._sortNodeDown(i);
  }

This is equivalent to using getParentIndexOf(this.heapArray.length - 1) and removes an unnecessary leaf‐node call without affecting correctness.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c6bce4c and 6a14ce5.

⛔ Files ignored due to path filters (2)
  • dist/heap-js.es5.js is excluded by !**/dist/**
  • dist/heap-js.umd.js is excluded by !**/dist/**
📒 Files selected for processing (12)
  • README.md (2 hunks)
  • docs/functions/toInt.html (1 hunks)
  • docs/index.html (2 hunks)
  • docs/types/AsyncComparator.html (1 hunks)
  • docs/types/AsyncIsEqual.html (1 hunks)
  • docs/types/Comparator.html (1 hunks)
  • docs/types/IsEqual.html (1 hunks)
  • package.json (1 hunks)
  • src/Heap.ts (5 hunks)
  • src/HeapAsync.ts (3 hunks)
  • tests/heap-async/heap-async-private-methods.test.ts (1 hunks)
  • tests/heap/heap-private-methods.test.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
src/HeapAsync.ts (1)
src/Heap.ts (1)
  • length (511-513)
src/Heap.ts (1)
src/HeapAsync.ts (1)
  • length (463-465)
🔇 Additional comments (16)
package.json (1)

3-3: LGTM! Version bump aligns with PR objectives.

The version increment from 2.6.0 to 2.7.0 is appropriate for a minor release that includes performance improvements and internal refactors.

tests/heap/heap-private-methods.test.ts (1)

1-1: LGTM! ESLint override is appropriate for private method tests.

The no-explicit-any override is reasonable here since this test file explicitly tests heap operations with various types including any. This aligns with the parallel change in the async heap test file.

docs/functions/toInt.html (1)

1-1: Documentation-only change: Repository reference updated.

The "Defined in" link has been updated from ignlg/heap-js to BeatsuDev/heap-js. This is a generated documentation file with no functional impact.

README.md (2)

46-50: LGTM: Version 2.7 changelog added.

The new changelog entry appropriately documents the performance improvements and acknowledges the contributor.


77-77: LGTM: Markdown link formatting corrected.

The closing bracket has been correctly moved to fix the URL formatting for the Java PriorityQueue reference.

docs/types/Comparator.html (1)

1-1: Documentation-only change: Repository reference updated.

The "Defined in" link has been updated from ignlg/heap-js to BeatsuDev/heap-js. This is a generated documentation file with no functional impact.

docs/index.html (1)

14-18: LGTM: Version 2.6 changelog section added to HTML documentation.

The changelog correctly documents the performance improvements and test/documentation enhancements for version 2.6, maintaining consistency with the README.

tests/heap-async/heap-async-private-methods.test.ts (1)

1-1: LGTM: ESLint directive added for test flexibility.

The no-explicit-any rule is appropriately disabled for this test file, which tests generic heap behavior across multiple type configurations. This is a reasonable accommodation for test code.

src/Heap.ts (5)

64-69: LGTM! Bit-shift optimization for parent index calculation.

The change from Math.floor((idx - 1) / 2) to (idx - 1) >> 1 is a standard performance optimization for binary heap parent index calculation. The bit-shift operation is mathematically equivalent and more efficient.


423-431: LGTM! Optimal heapify starting index.

Starting the heapify loop from Heap.getParentIndexOf(this.length - 1) is the correct optimization. This index represents the last non-leaf node in the heap, and all nodes after it are leaves that don't require sifting down. This is the standard Floyd's algorithm for O(n) heap construction.


805-809: LGTM! Swap optimization using temporary variable.

Replacing array destructuring with a temporary variable is a micro-optimization that avoids temporary array allocation. This can improve performance in the hot path of heap operations.


815-833: LGTM! Optimized sift-down implementation.

The refactored _sortNodeDown uses a standard optimization pattern:

  • Caches the original value to reduce array accesses
  • Computes the best child in a single step
  • Moves children up during traversal
  • Performs a single final assignment of the original value

This reduces the number of array writes and is a well-established heap performance optimization.


839-852: LGTM! Optimized sift-up implementation.

The refactored _sortNodeUp mirrors the _sortNodeDown optimization:

  • Caches the original value to reduce array accesses
  • Moves parents down during upward traversal
  • Performs a single final assignment at the correct position

This optimization reduces array writes and is consistent with the sift-down improvements.

src/HeapAsync.ts (3)

729-733: LGTM! Swap optimization using temporary variable.

Consistent with the optimization in src/Heap.ts, this replaces array destructuring with a temporary variable to avoid array allocation overhead.


739-759: LGTM! Async version of optimized sift-down.

The refactored _sortNodeDown correctly mirrors the optimization in src/Heap.ts with proper async/await handling for comparisons. The value caching and single-write pattern is preserved.


765-778: LGTM! Async version of optimized sift-up.

The refactored _sortNodeUp correctly mirrors the optimization in src/Heap.ts with proper async/await handling. The implementation is consistent and correct.

@ignlg ignlg merged commit fb03b86 into master Sep 30, 2025
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

Comments