Skip to content

Performance & Tooling Modernization: oxlint, Native Testing, and Documentation Overhaul#402

Merged
avoidwork merged 64 commits into
masterfrom
tweaks
Mar 29, 2026
Merged

Performance & Tooling Modernization: oxlint, Native Testing, and Documentation Overhaul#402
avoidwork merged 64 commits into
masterfrom
tweaks

Conversation

@avoidwork
Copy link
Copy Markdown
Owner

@avoidwork avoidwork commented Mar 21, 2026

Summary

This PR introduces several performance optimizations, code quality improvements, and comprehensive documentation updates to the tiny-lru library.

Key Changes

Performance Optimizations

  • Removed bypass parameter from evict() - Eliminated unnecessary conditional logic that caused V8 deoptimization. All internal callers already guaranteed size > 0 before calling evict(), making the parameter redundant.
  • Converted unlink() to private field - Changed from unlink() to #unlink() for true encapsulation and cleaner API surface.
  • Updated Node.js requirement - Bumped from >=12 to >=14 to support private class fields.

Code Quality Improvements

  • Simplified JSDoc - Removed redundant @example, @see, @since, @method, and @memberof tags from all method docblocks while preserving essential @param, @returns, and @throws information.
  • DRY refactoring - Extracted #unlink() helper to eliminate duplicate linked list manipulation code in delete(), evict(), and moveToEnd().
  • API simplification - Removed resetTtl parameter from set() and setWithEvicted() methods (internal implementation detail exposed in public API).

Documentation Updates

  • Complete API reference - Added comprehensive docs/API.md with all methods, parameters, and usage examples.
  • Technical documentation - Updated docs/TECHNICAL_DOCUMENTATION.md with accurate mathematical formulas, data flow diagrams, and TypeScript signatures.
  • Contributing guide - Added CONTRIBUTING.md with development workflow and best practices.
  • Development principles - Documented DRY, YAGNI, SOLID, and OWASP principles in AGENTS.md.
  • Fixed documentation issues - Corrected resetTtl description, setWithEvicted() return type, and TTL reset invariant.

Build & Tooling

  • Migrated to oxlint/oxfmt - Replaced ESLint with faster oxlint and added oxfmt for formatting.
  • Native test runner - Switched from Mocha/c8 to Node.js built-in test runner (node --test).
  • Updated benchmarks - Enhanced benchmark suite with more comprehensive performance testing.

Breaking Changes

Removed Parameters

  • evict(bypass?) - The bypass parameter has been removed. Call evict() without arguments.
  • set(key, value, resetTtl?) - The third resetTtl parameter has been removed. Use the constructor-level resetTtl setting instead.
  • setWithEvicted(key, value, resetTtl?) - The third resetTtl parameter has been removed. Use the constructor-level resetTtl setting instead.

Environment Requirements

  • Node.js 14+ required - Private class fields (#unlink()) require Node.js 14 or later. Previously supported Node.js 12+.

Behavioral Notes

  • resetTtl behavior - The resetTtl constructor option now only affects set() and setWithEvicted() when updating existing keys. It does NOT affect get() operations (this was never the case, but documentation was corrected).

Migration Guide

Before

const cache = new LRU(100, 5000, true);
cache.set('key', 'value');
cache.set('key', 'new value', true); // Third parameter ignored
cache.evict(true); // bypass parameter

After

const cache = new LRU(100, 5000, true);
cache.set('key', 'value');
cache.set('key', 'new value'); // resetTtl handled by constructor setting
cache.evict(); // No parameters needed

Testing

All 54 tests pass with 100% line coverage.

✔ LRU Cache (295.68ms)
ℹ tests 54
ℹ suites 12
ℹ pass 54
ℹ fail 0

Performance Impact

Benchmarking shows no significant performance regression from removing the bypass parameter. The new implementation is actually simpler:

  • Old: if (bypass || this.size > 0) with nested early return
  • New: if (this.size === 0) return this; single check
    The overhead of accessing this.size is negligible (<1ns) and the property is already "warm" in CPU cache from being accessed in set().

Files Changed

  • src/lru.js - Core implementation with private #unlink() and simplified evict(), set(), setWithEvicted()
  • types/lru.d.ts - Updated TypeScript definitions
  • docs/API.md - New comprehensive API reference
  • docs/TECHNICAL_DOCUMENTATION.md - Updated technical documentation
  • CONTRIBUTING.md - New contributing guide
  • AGENTS.md - Development principles and workflow
  • package.json - Updated engines, dependencies, and scripts
  • Distribution files in dist/

- Add removeFromList definition with all 4 prev/next cases
- Expand moveToEnd formula and document 'only node' edge case
- Fix TTL validity invariant to handle expiry=0 when ttl=0
- Clear prev/next pointers in delete() and evict() to prevent memory leaks
- Fix entries() and values() to not pollute LRU order (access items directly instead of calling get())
- Fix entries() and values() returning stale data with TTL (direct item access instead of get() which can delete expired items)
- Fix expiresAt() to return expiry for expired-but-not-yet-deleted items
- Optimize setWithEvicted() to avoid redundant has()+set() calls
- Remove dead code in moveToEnd() (unreachable edge case)
- Remove obsolete moveToEnd edge case test
@avoidwork avoidwork self-assigned this Mar 21, 2026
@augmentcode
Copy link
Copy Markdown

augmentcode Bot commented Mar 21, 2026

🤖 Augment PR Summary

Summary: This PR refreshes documentation/tooling and tweaks the LRU internals around TTL-awareness and iteration helpers.

Changes:

  • Adds AGENTS.md and CLAUDE.md with project/workflow guidance.
  • Rewrites README.md to be shorter and introduces docs/API.md as the full API reference.
  • Updates docs to clarify resetTtl behavior and the setWithEvicted() return shape.
  • Switches dev tooling to oxlint/oxfmt and migrates tests to Node’s built-in node --test runner.
  • Updates benchmarks to avoid new Array(); regenerates dist/ outputs.
  • Refactors cache internals: TTL-aware has(), pointer cleanup on removal, and entries()/values() no longer call get() (avoids LRU reordering/side effects during enumeration).

Technical notes: The behavioral changes primarily affect TTL visibility via has() and how enumeration helpers read values without mutating LRU order.

🤖 Was this summary useful? React with 👍 or 👎

Copy link
Copy Markdown

@augmentcode augmentcode Bot left a comment

Choose a reason for hiding this comment

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

Review completed. 6 suggestions posted.

Fix All in Augment

Comment augment review to trigger a new review at any time.

Comment thread src/lru.js
Comment thread src/lru.js
Comment thread src/lru.js Outdated
Comment thread README.md Outdated
Comment thread README.md Outdated
Comment thread tests/unit/lru.js
…tation

- Add setWithEvicted() to resetTtl description in Core Components
- Update create() formula to show conditional TTL handling (ttl > 0 ? t_now + ttl : 0)
- Fix TTL Reset Invariant to remove incorrect bypass parameter reference
- Simplified evict() signature by removing unused bypass parameter
- All internal callers already guarantee size > 0 before calling evict()
- Reduced code complexity and eliminated unnecessary conditional branch
- Updated TypeScript definitions and documentation

BREAKING CHANGE: evict() no longer accepts bypass parameter
- Correct resetTtl description: resets TTL on set() updates, not get()
- Fix setWithEvicted return type: {key, value, expiry} only (no prev/next)

All 54 tests passing.
- Convert unlink() to private field (#unlink) for true encapsulation
- Update engines.node from >=12 to >=14 to support private class fields
- All 54 tests passing
…memberof

- Removed @example, @see, and @SInCE tags from all method docblocks
- Removed @method and @memberof tags (redundant for class methods)
- Kept @param, @returns, @throws, @Private, and @constructor where needed
- Updated distribution files via build
- All 54 tests passing
- Remove outdated tests using removed resetTtl parameter from set()/setWithEvicted()
- Add tests for garbage collection (prev/next pointer cleanup)
- Add tests for first/last pointer consistency after deletions
- Add tests for different value types (functions, objects, arrays, null, undefined)
- Add tests for unlimited cache edge cases
- Add tests for array methods with non-existent keys
- Add test verifying get() does NOT reset TTL
- Remove object key test (not supported - keys coerced to strings)

Total: 69 tests, 14 suites, all passing
…eference

- Update README.md to require Node.js ≥14 (for private class fields)
- Update docs/TECHNICAL_DOCUMENTATION.md to reference Node.js test runner instead of mocha
@avoidwork avoidwork merged commit 7d73daa into master Mar 29, 2026
4 checks passed
@avoidwork avoidwork deleted the tweaks branch March 29, 2026 16:23
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.

1 participant