{"versions":{"1.0.0":{"name":"@asamuzakjp/generational-cache","description":"A generational pseudo-LRU cache with strict maximum size limits.","author":{"name":"asamuzaK"},"license":"MIT","homepage":"https://github.com/asamuzaK/generationalCache","bugs":{"url":"https://github.com/asamuzaK/generationalCache/issues"},"repository":{"type":"git","url":"git+https://github.com/asamuzaK/generationalCache.git"},"type":"module","exports":{".":{"types":"./types/index.d.ts","default":"./src/index.js"},"./package.json":"./package.json"},"devDependencies":{"@types/node":"^25.6.0","c8":"^11.0.0","commander":"^14.0.3","eslint":"^9.39.4","eslint-config-prettier":"^10.1.8","eslint-plugin-jsdoc":"^62.9.0","eslint-plugin-prettier":"^5.5.5","eslint-plugin-regexp":"^3.1.0","eslint-plugin-unicorn":"^64.0.0","globals":"^17.5.0","lru-cache":"^11.3.5","mitata":"^1.0.34","mnemonist":"^0.40.3","mocha":"^11.7.5","neostandard":"^0.13.0","prettier":"^3.8.2","quick-lru":"^7.3.0","typescript":"^6.0.2"},"overrides":{"c8":{"yargs":"^18.0.0"},"eslint":{"brace-expansion":"^1.1.13"},"serialize-javascript":"^7.0.4"},"scripts":{"bench":"node --expose-gc ./benchmark/benchmark.js","bench:worst":"node --expose-gc ./benchmark/worst-case-benchmark.js","build":"npm run tsc && npm run lint && npm test","lint":"eslint --fix .","test":"c8 --reporter=text mocha --exit test/*.test.js","tsc":"node scripts/index clean --dir=types -i && npx tsc"},"engines":{"node":"^20.19.0 || ^22.12.0 || >=24.0.0"},"version":"1.0.0","gitHead":"db5e7b1541d8378a8186f70ab69ba0351f341fc7","_id":"@asamuzakjp/generational-cache@1.0.0","_nodeVersion":"24.14.1","_npmVersion":"11.12.1","dist":{"integrity":"sha512-TfnObbgAt7vpjieBiiYg8zKUIgE4WFWIiLLQmW+GA8UF+gv/jxI72jUBx7Pg2EFiRkR+gm+/Wgi+dGi9i4M9tQ==","shasum":"8b38d03549d19eeee2af14bcd0e07c8165b3d56f","tarball":"http://123.232.10.234:8212/nexus/content/groups/npm-public/@asamuzakjp/generational-cache/-/generational-cache-1.0.0.tgz","fileCount":5,"unpackedSize":15565,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQClZxxfbsycABJwJvHW9+3tQnYwFkLytEw+NS+hnQlK6QIhAMJjWLMdh7PrzrusJbYSWtCNSnFZe1zkbldg5Mh1B3fu"}],"size":6014},"_npmUser":{"name":"anonymous","email":"info@asamuzak.jp"},"directories":{},"maintainers":[{"name":"anonymous","email":"info@asamuzak.jp"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/generational-cache_1.0.0_1776174324682_0.3405109213204798"},"_hasShrinkwrap":false,"_cnpmcore_publish_time":"2026-04-14T13:45:24.819Z","publish_time":1776174324819,"_source_registry_name":"default","contributors":[]},"0.1.0":{"name":"@asamuzakjp/generational-cache","version":"0.1.0","author":{"name":"asamuzaK"},"license":"MIT","_id":"@asamuzakjp/generational-cache@0.1.0","maintainers":[{"name":"anonymous","email":"info@asamuzak.jp"}],"homepage":"https://github.com/asamuzaK/generationalCache","bugs":{"url":"https://github.com/asamuzaK/generationalCache/issues"},"dist":{"shasum":"80973d026e84cc80f5215703eb7d94d8cd2b30d1","tarball":"http://123.232.10.234:8212/nexus/content/groups/npm-public/@asamuzakjp/generational-cache/-/generational-cache-0.1.0.tgz","fileCount":5,"integrity":"sha512-o3/d6CmVjESkhbaCAQlwmxwbVPILKSOIa+j1Q9w8pehf2LClap6b/pmtwQqAZRZW8ykON9tW4k+D4pAaTAk3AA==","signatures":[{"sig":"MEUCIQDdSaviYq6zGiLll2JTM0ZWiz9Xv0Xza6FcFReSUJAklAIgHaxqcZLn4L/b4UPxMj1IL3Xm+0Wxf6PrJjOY+zruyZ8=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":13541,"size":5295},"type":"module","engines":{"node":"^20.19.0 || ^22.12.0 || >=24.0.0"},"exports":{".":{"types":"./types/index.d.ts","default":"./src/index.js"},"./package.json":"./package.json"},"gitHead":"ad440d49ce15510717c6632d0784d552948b4a9c","scripts":{"tsc":"node scripts/index clean --dir=types -i && npx tsc","lint":"eslint --fix .","test":"c8 --reporter=text mocha --exit test/*.test.js","bench":"node --expose-gc ./benchmark/benchmark.js","build":"npm run tsc && npm run lint && npm test"},"_npmUser":{"name":"anonymous","email":"info@asamuzak.jp"},"overrides":{"c8":{"yargs":"^18.0.0"},"eslint":{"brace-expansion":"^1.1.13"},"serialize-javascript":"^7.0.4"},"repository":{"url":"git+https://github.com/asamuzaK/generationalCache.git","type":"git"},"_npmVersion":"11.12.1","description":"A generational pseudo-LRU cache with strict maximum size limits.","directories":{},"_nodeVersion":"24.14.1","_hasShrinkwrap":false,"devDependencies":{"c8":"^11.0.0","mocha":"^11.7.5","eslint":"^9.39.4","mitata":"^1.0.34","globals":"^17.4.0","prettier":"^3.8.2","commander":"^14.0.3","lru-cache":"^11.3.3","quick-lru":"^7.3.0","typescript":"^6.0.2","@types/node":"^25.6.0","neostandard":"^0.13.0","eslint-plugin-jsdoc":"^62.9.0","eslint-plugin-regexp":"^3.1.0","eslint-plugin-unicorn":"^64.0.0","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.5"},"_npmOperationalInternal":{"tmp":"tmp/generational-cache_0.1.0_1776001035474_0.9908591194162877","host":"s3://npm-registry-packages-npm-production"},"_cnpmcore_publish_time":"2026-04-12T13:37:15.622Z","publish_time":1776001035622,"_source_registry_name":"default","contributors":[]},"1.0.1":{"name":"@asamuzakjp/generational-cache","description":"A generational pseudo-LRU cache with strict maximum size limits.","author":{"name":"asamuzaK"},"license":"MIT","homepage":"https://github.com/asamuzaK/generationalCache","bugs":{"url":"https://github.com/asamuzaK/generationalCache/issues"},"repository":{"type":"git","url":"git+https://github.com/asamuzaK/generationalCache.git"},"type":"module","exports":{".":{"types":"./types/index.d.ts","default":"./src/index.js"},"./package.json":"./package.json"},"devDependencies":{"@types/node":"^25.6.0","c8":"^11.0.0","commander":"^14.0.3","eslint":"^9.39.4","eslint-config-prettier":"^10.1.8","eslint-plugin-jsdoc":"^62.9.0","eslint-plugin-prettier":"^5.5.5","eslint-plugin-regexp":"^3.1.0","eslint-plugin-unicorn":"^64.0.0","globals":"^17.5.0","lru-cache":"^11.3.5","mitata":"^1.0.34","mnemonist":"^0.40.3","mocha":"^11.7.5","neostandard":"^0.13.0","prettier":"^3.8.2","quick-lru":"^7.3.0","typescript":"^6.0.2"},"overrides":{"c8":{"yargs":"^18.0.0"},"eslint":{"brace-expansion":"^1.1.13"},"serialize-javascript":"^7.0.4"},"scripts":{"bench":"node --expose-gc ./benchmark/benchmark.js","bench:worst":"node --expose-gc ./benchmark/worst-case-benchmark.js","build":"npm run tsc && npm run lint && npm test","lint":"eslint --fix .","test":"c8 --reporter=text mocha --exit test/*.test.js","tsc":"node scripts/index clean --dir=types -i && npx tsc"},"engines":{"node":"^20.19.0 || ^22.12.0 || >=24.0.0"},"version":"1.0.1","gitHead":"3c6c8161198db5242f57e1168b94d429a862d937","_id":"@asamuzakjp/generational-cache@1.0.1","_nodeVersion":"24.14.1","_npmVersion":"11.12.1","dist":{"integrity":"sha512-wajfB8KqzMCN2KGNFdLkReeHncd0AslUSrvHVvvYWuU8ghncRJoA50kT3zP9MVL0+9g4/67H+cdvBskj9THPzg==","shasum":"3d0bf6be4fc059851390a7070720c6007af793ec","tarball":"http://123.232.10.234:8212/nexus/content/groups/npm-public/@asamuzakjp/generational-cache/-/generational-cache-1.0.1.tgz","fileCount":5,"unpackedSize":14453,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQD/jjIpobdNCqCa/XOZ7cO9OLq4NWzkGfKzwtQeBV/m4AIgMHUdMISoglflH+93hTqi7yrde/mj2GAuxBX8KjnP3jE="}],"size":5554},"_npmUser":{"name":"anonymous","email":"info@asamuzak.jp"},"directories":{},"maintainers":[{"name":"anonymous","email":"info@asamuzak.jp"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/generational-cache_1.0.1_1776201252451_0.9448158210822566"},"_hasShrinkwrap":false,"_cnpmcore_publish_time":"2026-04-14T21:14:12.580Z","publish_time":1776201252580,"_source_registry_name":"default","contributors":[]}},"dist-tags":{"latest":"1.0.1","next":"0.1.0"},"name":"@asamuzakjp/generational-cache","time":{"created":"2026-04-14T13:45:37.756Z","modified":"2026-04-14T21:14:26.790Z","1.0.0":"2026-04-14T13:45:24.819Z","0.1.0":"2026-04-12T13:37:15.622Z","1.0.1":"2026-04-14T21:14:12.580Z"},"readme":"# generational-cache\n\n[![CI](https://github.com/asamuzaK/generationalCache/actions/workflows/ci.yaml/badge.svg)](https://github.com/asamuzaK/generationalCache/actions/workflows/ci.yaml)\n[![CodeQL](https://github.com/asamuzaK/generationalCache/actions/workflows/github-code-scanning/codeql/badge.svg)](https://github.com/asamuzaK/generationalCache/actions/workflows/github-code-scanning/codeql)\n[![npm (scoped)](https://img.shields.io/npm/v/@asamuzakjp/generational-cache)](https://www.npmjs.com/package/@asamuzakjp/generational-cache)\n\nA lightweight, **generational pseudo-LRU (Least Recently Used) cache** with strict maximum size limits.\n\n## How it Works\n\n`GenerationalCache` maintains two internal `Map` objects: `current` and `old`.\n\n1.  **Insertion**: New items are always added to the `current` generation.\n2.  **Promotion**: If you `get` an item that exists in the `old` generation, it is promoted to the `current` generation to ensure it stays in the cache longer.\n3.  **Generation Swapping**: Once the `current` generation reaches the boundary size ($max / 2$), the `old` generation is discarded, the `current` generation becomes the `old` generation, and a new empty `current` generation is created.\n\nThis \"pseudo-LRU\" approach avoids the overhead of updating timestamps or complex linked list pointers on every single access.\n\n## Installation\n```bash\nnpm i @asamuzakjp/generational-cache\n```\n\n## Usage\n```javascript\nimport { GenerationalCache } from '@asamuzakjp/generational-cache';\n\n// Initialize with a max capacity of 1024 items\nconst cache = new GenerationalCache(1024);\n```\n\n## API\n\n### `new GenerationalCache(max)`\n\nCreates a new cache instance.\n\n* **`max`** *(number)*: The maximum number of items the cache can hold.\n  If the specified value is less than 4, or if an invalid value is specified, the default value of 4 will be used.\n\n### Properties\n\n* **`cache.size`** *(number, read-only)*: Returns the total number of *entries* currently in the cache.\n  **Note:** To optimize for write speed, this library allows temporary key duplication between generations.\n  Therefore, this value may not always reflect the exact count of unique *keys*.\n* **`cache.max`** *(number)*: Gets or sets the maximum capacity.\n  **Note:** Updating this property dynamically will invoke `cache.clear()` to safely recalculate boundaries.\n\n### Methods\n\n* **`cache.get(key)`**\n  Retrieves an item.\n  If the item is found in the older generation, it is automatically promoted to the current generation to prevent it from being evicted during the next swap.\n    * **Returns:** The value associated with the key, or `undefined`.\n* **`cache.set(key, value)`**\n  Adds or updates an item. If adding this item pushes the current generation's size to the boundary threshold (`max / 2`), a generation swap is triggered, and the old generation is discarded.\n    * **Returns:** The cache instance itself (allows chaining).\n* **`cache.has(key)`**\n  Checks if a key exists in the cache (in either generation).\n    * **Returns:** `true` if the key exists, otherwise `false`.\n* **`cache.delete(key)`**\n  Removes an item from the cache.\n    * **Returns:** `true` if the item existed and was removed, otherwise `false`.\n* **`cache.clear()`**\n  Empties all items from the cache by dropping references to the internal Maps.\n\n## Performance\n\nBenchmarks are divided into two states to simulate real-world conditions:\n- **Cold State**: Measured with aggressive internal Garbage Collection to observe performance before full V8 TurboFan optimizations.\n- **Warm State**: Measured after sufficient warmup, representing sustained throughput under optimal JIT compilation.\n\n*The results below reflect the sustained operations per second (ops/sec), calculated from the average latency (`ns/iter`). Higher values indicate better performance.*\n\n### Benchmark Environment\n- **Engine:** Node.js v24.x (V8)\n- **Measurement:** [mitata](https://github.com/evanwashere/mitata).\n- **Comparison:** [LRUCache](https://www.npmjs.com/package/lru-cache) (v11.x), [QuickLRU](https://www.npmjs.com/package/quick-lru) (v7.x), [Mnemonist](https://www.npmjs.com/package/mnemonist) (v0.40.x)\n\n### 1. Small Cache (Max Size = 512)\n| Scenario | State | **GenerationalCache** | LRUCache | QuickLRU | Mnemonist |\n| :--- | :--- | :--- | :--- | :--- | :--- |\n| **Set** | Cold | **17,733,640 ops/sec** | 4,933,885 ops/sec | 13,506,212 ops/sec | **17,229,496 ops/sec** |\n| | Warm | **23,030,861 ops/sec** | 15,216,068 ops/sec | 18,175,209 ops/sec | 19,409,937 ops/sec |\n| **Get** | Cold | 17,717,930 ops/sec | 7,633,587 ops/sec | 13,734,377 ops/sec | **30,731,407 ops/sec** |\n| | Warm | 21,724,961 ops/sec | 24,148,756 ops/sec | 16,385,384 ops/sec | **35,688,793 ops/sec** |\n| **Eviction** | Cold | **16,700,066 ops/sec** | 6,953,619 ops/sec | 13,285,505 ops/sec | 4,925,865 ops/sec |\n| | Warm | **23,148,148 ops/sec** | 9,040,773 ops/sec | 16,903,313 ops/sec | 8,037,293 ops/sec |\n\n### 2. Medium Cache (Max Size = 2,048)\n| Scenario | State | **GenerationalCache** | LRUCache | QuickLRU | Mnemonist |\n| :--- | :--- | :--- | :--- | :--- | :--- |\n| **Set** | Cold | **15,987,210 ops/sec** | 4,874,957 ops/sec | 11,849,745 ops/sec | **15,309,246 ops/sec** |\n| | Warm | **19,716,088 ops/sec** | 13,345,789 ops/sec | 14,755,791 ops/sec | 17,325,017 ops/sec |\n| **Get** | Cold | 14,994,751 ops/sec | 7,950,389 ops/sec | 11,503,508 ops/sec | **23,651,844 ops/sec** |\n| | Warm | 17,825,311 ops/sec | 18,789,928 ops/sec | 13,838,915 ops/sec | **31,289,111 ops/sec** |\n| **Eviction** | Cold | **16,355,904 ops/sec** | 6,757,669 ops/sec | 12,074,378 ops/sec | 5,175,983 ops/sec |\n| | Warm | **21,982,853 ops/sec** | 8,089,305 ops/sec | 15,309,246 ops/sec | 7,132,158 ops/sec |\n\n### 3. Large Cache (Max Size = 8,192)\n| Scenario | State | **GenerationalCache** | LRUCache | QuickLRU | Mnemonist |\n| :--- | :--- | :--- | :--- | :--- | :--- |\n| **Set** | Cold | **13,679,890 ops/sec** | 3,954,288 ops/sec | 8,126,777 ops/sec | 10,972,130 ops/sec |\n| | Warm | **20,593,080 ops/sec** | 12,054,001 ops/sec | 12,995,451 ops/sec | 15,600,624 ops/sec |\n| **Get** | Cold | 11,918,951 ops/sec | 5,785,363 ops/sec | 9,067,827 ops/sec | **16,784,155 ops/sec** |\n| | Warm | 16,781,339 ops/sec | 17,247,326 ops/sec | 12,733,987 ops/sec | **31,436,655 ops/sec** |\n| **Eviction** | Cold | **13,561,160 ops/sec** | 5,510,249 ops/sec | 9,642,271 ops/sec | 4,040,404 ops/sec |\n| | Warm | **21,128,248 ops/sec** | 7,082,152 ops/sec | 13,208,294 ops/sec | 6,023,007 ops/sec |\n\n### 4. Cyclic Access (Max Size = 8,192 / Working Set = 5,000)\n| Metric | **GenerationalCache** | LRUCache | QuickLRU | Mnemonist |\n| :--- | :--- | :--- | :--- | :--- |\n| **Hit Rate** | 78.30% | **100.00%** | **100.00%** | **100.00%** |\n| **Throughput** | 10,365,916 ops/sec | 40,832,993 ops/sec | 40,950,040 ops/sec | **48,426,150 ops/sec** |\n\n## Key Characteristics\n\n* **High Eviction Efficiency**: `GenerationalCache` demonstrates strong throughput during high-turnover workloads, maintaining a performance margin compared to standard LRU designs in large-scale eviction scenarios.\n* **Predictable Scalability**: While other libraries may experience performance degradation as cache size increases, `GenerationalCache` maintains consistent throughput due to its generational swap mechanism.\n* **Balanced Read/Write**: It provides stable and competitive performance across all basic operations (`get`, `set`), making it suitable for both read-heavy and write-heavy environments.\n* **Trade-offs**: In cyclic access patterns where the working set is greater than `max / 2` but smaller than `max`, `GenerationalCache` will experience frequent generation swaps and cache misses. To maximize the performance benefits of `GenerationalCache`, it is often better to keep the `max` size small enough to allow some evictions, rather than trying to fit the entire working set.\n\n## License\n\nMIT","users":{}}