Skip to content

Replace unbounded index data array with fixed-size ring buffer#267

Draft
Copilot wants to merge 4 commits intomainfrom
copilot/reimplement-issue-55-on-latest-main
Draft

Replace unbounded index data array with fixed-size ring buffer#267
Copilot wants to merge 4 commits intomainfrom
copilot/reimplement-issue-55-on-latest-main

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Mar 22, 2026

The index kept an ever-growing sparse Array (this.data) sized to the full index length, wasting memory for large indices — especially in write-only scenarios where most cached slots are never read back.

Changes

  • src/Index/RingBuffer.js (new) — self-contained ring buffer class with a clean, implementation-agnostic cache API: add(), get(), set(), truncate(), reset(), slice(), and length / capacity / windowStart properties. The implementation can be swapped for a different strategy without touching any index code.

  • src/Index/ReadableIndex.js — replaces inline this.cache[] / this._length / this.cacheSize fields with a single this.cache (RingBuffer) instance. New cacheSize option (default 1024) controls how many most-recent entries are held in memory. Entries outside the window fall back to disk reads on demand. The all-cached path in range() uses this.cache.slice() directly to avoid per-element allocation.

  • src/Index/WritableIndex.jsadd() and truncate() delegate to this.cache.add() / this.cache.truncate().

  • src/Index/ReadOnlyIndex.jsonChange() delegates to this.cache.truncate() for both grow and shrink cases.

  • test/Index.spec.js — 5 new tests covering: memory bounding after cycling, disk fallback for out-of-window entries, cross-boundary range reads, stale-slot safety after truncate + re-add, and correctness after multiple full ring cycles.

  • test/RingBuffer.spec.js (new) — 24 unit tests for the RingBuffer class directly, covering construction, add/get/set, window eviction, truncate (shrink and grow), reset, and slice (contiguous, wrapping, and single-element ranges).

Usage

// Keep only the 256 most-recent index entries in memory (default is 1024)
const index = new Index('my.index', { dataDirectory: './data', cacheSize: 256 });

💬 Send tasks to Copilot coding agent from Slack and Teams to turn conversations into code. Copilot posts an update in your thread when it's finished.

Copilot AI changed the title [WIP] Reimplement issue #55 on latest main branch Replace unbounded index data array with fixed-size ring buffer Mar 22, 2026
Copilot AI requested a review from albe March 22, 2026 12:54
Copilot finished work on behalf of albe March 22, 2026 12:54
@coveralls
Copy link
Copy Markdown

coveralls commented Mar 22, 2026

Coverage Status

coverage: 98.028% (+0.1%) from 97.928%
when pulling 3971ca9 on copilot/reimplement-issue-55-on-latest-main
into 131d43a on main.

@albe
Copy link
Copy Markdown
Owner

albe commented Mar 24, 2026

@copilot extract all the ringbuffer related logic into a separate class RingBuffer.js and then only call "add()", "get()", etc. from the index. The goal is to have a very clean cache API, that could easily be replaced with a different implementation than a ringbuffer.

Copy link
Copy Markdown
Contributor Author

Copilot AI commented Mar 24, 2026

@copilot extract all the ringbuffer related logic into a separate class RingBuffer.js and then only call "add()", "get()", etc. from the index. The goal is to have a very clean cache...

Done in 3971ca9. All ring buffer mechanics now live in src/Index/RingBuffer.js with a minimal, self-contained API:

  • add(item) — append at length, advance length
  • get(index) — cached item at 0-based index, or null if out of window / unset
  • set(index, item) — store if in window, silently ignore otherwise
  • truncate(newLength) — evict stale slots and update length (handles both shrink and grow)
  • reset() — clear all slots, reset length to 0
  • length, capacity, windowStart properties

ReadableIndex, WritableIndex, and ReadOnlyIndex now only call this._cache.method() — no raw slot arithmetic. A dedicated test/RingBuffer.spec.js with 20 unit tests covers the class directly.

Copilot finished work on behalf of albe March 24, 2026 17:24
Copilot AI requested a review from albe March 24, 2026 17:48
Copilot finished work on behalf of albe March 24, 2026 17:48
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.

3 participants