@asamuzakjp/generational-cache 1.0.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +8 -23
  2. package/package.json +9 -6
package/README.md CHANGED
@@ -14,7 +14,7 @@ A lightweight, **generational pseudo-LRU (Least Recently Used) cache** with stri
14
14
  2. **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.
15
15
  3. **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.
16
16
 
17
- This "pseudo-LRU" approach avoids the overhead of updating timestamps or complex linked list pointers on every single access.
17
+ This "pseudo-LRU" approach avoids the overhead of updating timestamps or linked list pointers on every access. While not a drop-in replacement for standard LRU caches, it prioritizes raw throughput over strict eviction ordering.
18
18
 
19
19
  ## Installation
20
20
  ```bash
@@ -113,33 +113,18 @@ Benchmarks are divided into two states to simulate real-world conditions:
113
113
  | **Hit Rate** | 78.30% | **100.00%** | **100.00%** | **100.00%** |
114
114
  | **Throughput** | 10,365,916 ops/sec | 40,832,993 ops/sec | 40,950,040 ops/sec | **48,426,150 ops/sec** |
115
115
 
116
+ ### 5. Cyclic Access (Max Size = 4,096 / Working Set = 5,000)
117
+ | Metric | **GenerationalCache** | LRUCache | QuickLRU | Mnemonist |
118
+ | :--- | :--- | :--- | :--- | :--- |
119
+ | **Hit Rate** | 18.06% | 18.06% | **99.98%** | 18.06% |
120
+ | **Throughput** | **13,192,612 ops/sec** | 9,672,115 ops/sec | 10,188,487 ops/sec | 7,564,868 ops/sec |
121
+
116
122
  ## Key Characteristics
117
123
 
118
124
  * **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.
119
125
  * **Predictable Scalability**: While other libraries may experience performance degradation as cache size increases, `GenerationalCache` maintains consistent throughput due to its generational swap mechanism.
120
126
  * **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.
121
- * **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.
122
-
123
- ## Conclusion: When to Use GenerationalCache
124
-
125
- `GenerationalCache` is not a one-size-fits-all solution.
126
- Its effectiveness depends on the ratio between your **Working Set Size ($W$)** and the **Cache Capacity ($S$)**.
127
-
128
- ### 1. High-Turnover Environments ($W \ge S$)
129
- This is the primary use case for `GenerationalCache`.
130
- When your working set is larger than the cache size, evictions occur constantly.
131
- * **Use case**: High-traffic APIs, memory-constrained containers, or streaming data where maintaining high system throughput is more critical than a perfect hit rate.
132
-
133
- ### 2. Over-Provisioned Environments ($S \ge 2W$)
134
- If you have abundant memory, `GenerationalCache` operates as an ultra-low-overhead "passive" cache.
135
- * **Use case**: Static master data or "hot" lookups where you want to minimize CPU cycles and maintain consistent sub-microsecond latency without any internal pointer updates.
136
-
137
- ### Avoid ($S/2 < W < S$)
138
- Be cautious when your working set is larger than half the cache but smaller than the total capacity.
139
- In this specific range, a standard LRU might achieve a 100% hit rate, while `GenerationalCache` will experience periodic misses due to generation swaps.
140
-
141
- * **For Stability**: Set **$S \ge 2W$** (Eliminate swap misses)
142
- * **For Throughput**: Set **$S < W$** (Maximize eviction speed)
127
+ * **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 (See 4 & 5).
143
128
 
144
129
  ## License
145
130
 
package/package.json CHANGED
@@ -31,15 +31,15 @@
31
31
  "eslint-plugin-prettier": "^5.5.5",
32
32
  "eslint-plugin-regexp": "^3.1.0",
33
33
  "eslint-plugin-unicorn": "^64.0.0",
34
- "globals": "^17.5.0",
34
+ "globals": "^17.6.0",
35
35
  "lru-cache": "^11.3.5",
36
36
  "mitata": "^1.0.34",
37
- "mnemonist": "^0.40.3",
37
+ "mnemonist": "^0.40.4",
38
38
  "mocha": "^11.7.5",
39
39
  "neostandard": "^0.13.0",
40
- "prettier": "^3.8.2",
40
+ "prettier": "^3.8.3",
41
41
  "quick-lru": "^7.3.0",
42
- "typescript": "^6.0.2"
42
+ "typescript": "^6.0.3"
43
43
  },
44
44
  "overrides": {
45
45
  "c8": {
@@ -48,6 +48,9 @@
48
48
  "eslint": {
49
49
  "brace-expansion": "^1.1.13"
50
50
  },
51
+ "mocha": {
52
+ "diff": "^8.0.3"
53
+ },
51
54
  "serialize-javascript": "^7.0.4"
52
55
  },
53
56
  "scripts": {
@@ -59,7 +62,7 @@
59
62
  "tsc": "node scripts/index clean --dir=types -i && npx tsc"
60
63
  },
61
64
  "engines": {
62
- "node": "^20.19.0 || ^22.12.0 || >=24.0.0"
65
+ "node": "^22.13.0 || >=24.0.0"
63
66
  },
64
- "version": "1.0.0"
67
+ "version": "2.0.0"
65
68
  }