fast-map-cache 1.1.0 → 1.1.1
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.
- package/README.md +6 -6
- package/README_zh-CN.md +6 -6
- package/dist/main.d.mts +9 -11
- package/dist/main.d.ts +9 -11
- package/dist/main.js +56 -127
- package/dist/main.mjs +18 -45
- package/package.json +25 -16
package/README.md
CHANGED
|
@@ -13,7 +13,7 @@ A high-performance in-memory LRU cache for Node.js and browsers, implemented wit
|
|
|
13
13
|
|
|
14
14
|
In real-world scenarios, `fast-map-cache` demonstrates significant performance gains by preventing expensive operations:
|
|
15
15
|
|
|
16
|
-
- **🚀
|
|
16
|
+
- **🚀 Measured Benefits**: In the simulated API and CPU-bound workloads included in this repo, caching reduced end-to-end work by roughly **2x to 6x** when it could avoid expensive operations. Results depend on hit rate and workload cost.
|
|
17
17
|
|
|
18
18
|
For a detailed analysis, see the full [**Performance Report**](./docs/performance-report.md).
|
|
19
19
|
|
|
@@ -99,7 +99,7 @@ For more advanced use cases, including batch operations and presets, please see
|
|
|
99
99
|
|
|
100
100
|
## API Reference
|
|
101
101
|
|
|
102
|
-
The cache instance
|
|
102
|
+
The cache instance created by `createCache` implements `IFastCache`. `FastCacheWithTTL` additionally satisfies `IFastTTLCache` and exposes `cleanup()` and `destroy()`.
|
|
103
103
|
|
|
104
104
|
### `get(key: K): V | undefined`
|
|
105
105
|
|
|
@@ -125,11 +125,11 @@ Clears all items from the cache.
|
|
|
125
125
|
|
|
126
126
|
### `getMany(keys: K[]): Map<K, V>`
|
|
127
127
|
|
|
128
|
-
Retrieves multiple values for an array of keys. Returns a `Map` containing the found key-value pairs.
|
|
128
|
+
Retrieves multiple values for an array of keys. Returns a `Map` containing the found key-value pairs. This is a convenience API, not a guaranteed performance optimization.
|
|
129
129
|
|
|
130
130
|
### `setMany(entries: [K, V][]): void`
|
|
131
131
|
|
|
132
|
-
Adds or updates multiple key-value pairs from an array of entries.
|
|
132
|
+
Adds or updates multiple key-value pairs from an array of entries. This is a convenience API, not a guaranteed performance optimization.
|
|
133
133
|
|
|
134
134
|
### `size: number` (getter)
|
|
135
135
|
|
|
@@ -160,13 +160,13 @@ Manually triggers the cleanup of expired items. Returns the number of items that
|
|
|
160
160
|
|
|
161
161
|
### `destroy(): void` (For `FastCacheWithTTL` only)
|
|
162
162
|
|
|
163
|
-
Clears the automatic cleanup timer if `autoCleanup` was enabled.
|
|
163
|
+
Clears the automatic cleanup timer if `autoCleanup` was enabled. Useful for proactively releasing timer resources in long-lived processes or tests.
|
|
164
164
|
|
|
165
165
|
## Benchmark
|
|
166
166
|
|
|
167
167
|
This library is designed for high performance in real-world scenarios. The core value of a cache is not just the raw speed of its `get`/`set` operations, but its ability to prevent expensive computations or network requests.
|
|
168
168
|
|
|
169
|
-
|
|
169
|
+
The included benchmarks show clear gains when cache hits avoid expensive work such as simulated API calls or CPU-heavy computations. Actual results depend on hit rate, cache size, and the real cost of the work being skipped.
|
|
170
170
|
|
|
171
171
|
## Contributing
|
|
172
172
|
|
package/README_zh-CN.md
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
|
|
14
14
|
在真实业务场景中,`fast-map-cache` 通过有效避免高成本操作,展现出显著的性能优势:
|
|
15
15
|
|
|
16
|
-
- **🚀
|
|
16
|
+
- **🚀 可复核收益**: 在仓库自带的模拟 API 与 CPU 密集场景里,当缓存命中能够避开昂贵操作时,端到端收益大致在 **2 到 6 倍**。实际效果仍取决于命中率和被缓存工作的成本。
|
|
17
17
|
|
|
18
18
|
详细分析请参阅完整的 [**性能报告**](./docs/performance-report.md)。
|
|
19
19
|
|
|
@@ -99,7 +99,7 @@ cache.destroy()
|
|
|
99
99
|
|
|
100
100
|
## API 参考
|
|
101
101
|
|
|
102
|
-
|
|
102
|
+
`createCache` 返回实现 `IFastCache` 的实例。`FastCacheWithTTL` 进一步满足 `IFastTTLCache`,并额外提供 `cleanup()` 和 `destroy()`。
|
|
103
103
|
|
|
104
104
|
### `get(key: K): V | undefined`
|
|
105
105
|
|
|
@@ -125,11 +125,11 @@ cache.destroy()
|
|
|
125
125
|
|
|
126
126
|
### `getMany(keys: K[]): Map<K, V>`
|
|
127
127
|
|
|
128
|
-
根据键数组批量获取值。返回一个包含已找到的键值对的 `Map
|
|
128
|
+
根据键数组批量获取值。返回一个包含已找到的键值对的 `Map`。这是便捷 API,不保证一定比逐个调用更快。
|
|
129
129
|
|
|
130
130
|
### `setMany(entries: [K, V][]): void`
|
|
131
131
|
|
|
132
|
-
|
|
132
|
+
通过一个条目数组批量添加或更新键值对。这是便捷 API,不保证一定比逐个调用更快。
|
|
133
133
|
|
|
134
134
|
### `size: number` (getter)
|
|
135
135
|
|
|
@@ -160,13 +160,13 @@ cache.destroy()
|
|
|
160
160
|
|
|
161
161
|
### `destroy(): void` (仅 `FastCacheWithTTL` 可用)
|
|
162
162
|
|
|
163
|
-
如果开启了 `autoCleanup
|
|
163
|
+
如果开启了 `autoCleanup`,此方法用于清除自动清理定时器,适合在长生命周期进程或测试中主动释放资源。
|
|
164
164
|
|
|
165
165
|
## 性能基准
|
|
166
166
|
|
|
167
167
|
本库为真实场景下的高性能而设计。缓存的核心价值不仅在于 `get`/`set` 操作的原始速度,更在于它能够有效避免昂贵的计算或网络请求。
|
|
168
168
|
|
|
169
|
-
|
|
169
|
+
仓库内自带的 benchmark 显示:当缓存命中可以避开昂贵的 I/O 或 CPU 计算时,收益会很明显。实际效果主要取决于命中率、缓存容量是否覆盖热点集,以及被缓存工作的真实成本。
|
|
170
170
|
|
|
171
171
|
## 贡献
|
|
172
172
|
|
package/dist/main.d.mts
CHANGED
|
@@ -30,6 +30,10 @@ interface IFastCache<K extends CacheKey, V> {
|
|
|
30
30
|
getStats(): CacheStats;
|
|
31
31
|
cleanup?(): number;
|
|
32
32
|
}
|
|
33
|
+
interface IFastTTLCache<K extends CacheKey, V> extends IFastCache<K, V> {
|
|
34
|
+
cleanup(): number;
|
|
35
|
+
destroy(): void;
|
|
36
|
+
}
|
|
33
37
|
interface CacheNode<K extends CacheKey, V> {
|
|
34
38
|
key: K;
|
|
35
39
|
value: V;
|
|
@@ -81,12 +85,11 @@ declare class FastCache<K extends CacheKey, V> implements IFastCache<K, V> {
|
|
|
81
85
|
* 以实现 O(M) 复杂度的过期项目清理(M 为过期数量)。
|
|
82
86
|
*
|
|
83
87
|
* @important 在 Node.js 环境下使用 `autoCleanup: true` 时,
|
|
84
|
-
*
|
|
85
|
-
*
|
|
88
|
+
* 内部定时器在支持的运行时会调用 `unref()`,因此通常不会单独阻止进程退出。
|
|
89
|
+
* 如果缓存生命周期明确,仍建议调用 `destroy()` 主动清理定时器。
|
|
86
90
|
*/
|
|
87
|
-
declare class FastCacheWithTTL<K extends CacheKey, V> extends FastCache<K, V> {
|
|
91
|
+
declare class FastCacheWithTTL<K extends CacheKey, V> extends FastCache<K, V> implements IFastTTLCache<K, V> {
|
|
88
92
|
private readonly ttl;
|
|
89
|
-
private readonly autoCleanup;
|
|
90
93
|
private cleanupTimer;
|
|
91
94
|
private readonly timeHead;
|
|
92
95
|
private readonly timeTail;
|
|
@@ -97,15 +100,10 @@ declare class FastCacheWithTTL<K extends CacheKey, V> extends FastCache<K, V> {
|
|
|
97
100
|
delete(key: K): boolean;
|
|
98
101
|
clear(): void;
|
|
99
102
|
has(key: K): boolean;
|
|
100
|
-
get size(): number;
|
|
101
|
-
get capacity(): number;
|
|
102
|
-
setMany(entries: [K, V][]): void;
|
|
103
|
-
getMany(keys: K[]): Map<K, V>;
|
|
104
103
|
getStats(): CacheStats;
|
|
105
104
|
cleanup(): number;
|
|
106
105
|
/**
|
|
107
|
-
*
|
|
108
|
-
* 如果开启了 `autoCleanup`,你应当在应用关闭前调用此方法。
|
|
106
|
+
* 清理自动清理定时器,适合在可控生命周期中主动释放资源。
|
|
109
107
|
*/
|
|
110
108
|
destroy(): void;
|
|
111
109
|
/**
|
|
@@ -128,4 +126,4 @@ declare const CachePresets: {
|
|
|
128
126
|
readonly tempCache: <T>(maxSize?: number, ttl?: number) => FastCacheWithTTL<string, T>;
|
|
129
127
|
};
|
|
130
128
|
//#endregion
|
|
131
|
-
export { type CacheKey, type CacheNode, type CacheOptions, CachePresets, type CacheStats, FastCache, FastCacheWithTTL, type IFastCache, createCache, createCacheWithTTL };
|
|
129
|
+
export { type CacheKey, type CacheNode, type CacheOptions, CachePresets, type CacheStats, FastCache, FastCacheWithTTL, type IFastCache, type IFastTTLCache, createCache, createCacheWithTTL };
|
package/dist/main.d.ts
CHANGED
|
@@ -30,6 +30,10 @@ interface IFastCache<K extends CacheKey, V> {
|
|
|
30
30
|
getStats(): CacheStats;
|
|
31
31
|
cleanup?(): number;
|
|
32
32
|
}
|
|
33
|
+
interface IFastTTLCache<K extends CacheKey, V> extends IFastCache<K, V> {
|
|
34
|
+
cleanup(): number;
|
|
35
|
+
destroy(): void;
|
|
36
|
+
}
|
|
33
37
|
interface CacheNode<K extends CacheKey, V> {
|
|
34
38
|
key: K;
|
|
35
39
|
value: V;
|
|
@@ -81,12 +85,11 @@ declare class FastCache<K extends CacheKey, V> implements IFastCache<K, V> {
|
|
|
81
85
|
* 以实现 O(M) 复杂度的过期项目清理(M 为过期数量)。
|
|
82
86
|
*
|
|
83
87
|
* @important 在 Node.js 环境下使用 `autoCleanup: true` 时,
|
|
84
|
-
*
|
|
85
|
-
*
|
|
88
|
+
* 内部定时器在支持的运行时会调用 `unref()`,因此通常不会单独阻止进程退出。
|
|
89
|
+
* 如果缓存生命周期明确,仍建议调用 `destroy()` 主动清理定时器。
|
|
86
90
|
*/
|
|
87
|
-
declare class FastCacheWithTTL<K extends CacheKey, V> extends FastCache<K, V> {
|
|
91
|
+
declare class FastCacheWithTTL<K extends CacheKey, V> extends FastCache<K, V> implements IFastTTLCache<K, V> {
|
|
88
92
|
private readonly ttl;
|
|
89
|
-
private readonly autoCleanup;
|
|
90
93
|
private cleanupTimer;
|
|
91
94
|
private readonly timeHead;
|
|
92
95
|
private readonly timeTail;
|
|
@@ -97,15 +100,10 @@ declare class FastCacheWithTTL<K extends CacheKey, V> extends FastCache<K, V> {
|
|
|
97
100
|
delete(key: K): boolean;
|
|
98
101
|
clear(): void;
|
|
99
102
|
has(key: K): boolean;
|
|
100
|
-
get size(): number;
|
|
101
|
-
get capacity(): number;
|
|
102
|
-
setMany(entries: [K, V][]): void;
|
|
103
|
-
getMany(keys: K[]): Map<K, V>;
|
|
104
103
|
getStats(): CacheStats;
|
|
105
104
|
cleanup(): number;
|
|
106
105
|
/**
|
|
107
|
-
*
|
|
108
|
-
* 如果开启了 `autoCleanup`,你应当在应用关闭前调用此方法。
|
|
106
|
+
* 清理自动清理定时器,适合在可控生命周期中主动释放资源。
|
|
109
107
|
*/
|
|
110
108
|
destroy(): void;
|
|
111
109
|
/**
|
|
@@ -128,4 +126,4 @@ declare const CachePresets: {
|
|
|
128
126
|
readonly tempCache: <T>(maxSize?: number, ttl?: number) => FastCacheWithTTL<string, T>;
|
|
129
127
|
};
|
|
130
128
|
//#endregion
|
|
131
|
-
export { type CacheKey, type CacheNode, type CacheOptions, CachePresets, type CacheStats, FastCache, FastCacheWithTTL, type IFastCache, createCache, createCacheWithTTL };
|
|
129
|
+
export { type CacheKey, type CacheNode, type CacheOptions, CachePresets, type CacheStats, FastCache, FastCacheWithTTL, type IFastCache, type IFastTTLCache, createCache, createCacheWithTTL };
|
package/dist/main.js
CHANGED
|
@@ -1,102 +1,55 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
}
|
|
11
|
-
var __copyProps = (to, from, except, desc) => {
|
|
12
|
-
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
13
|
-
key = keys[i];
|
|
14
|
-
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
|
|
15
|
-
get: ((k) => from[k]).bind(null, key),
|
|
16
|
-
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
17
|
-
});
|
|
18
|
-
}
|
|
19
|
-
return to;
|
|
20
|
-
};
|
|
21
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
22
|
-
value: mod,
|
|
23
|
-
enumerable: true
|
|
24
|
-
}) : target, mod));
|
|
25
|
-
|
|
26
|
-
//#endregion
|
|
27
|
-
|
|
28
|
-
//#region node_modules/.pnpm/@oxc-project+runtime@0.80.0/node_modules/@oxc-project/runtime/src/helpers/typeof.js
|
|
29
|
-
var require_typeof = /* @__PURE__ */ __commonJS({ "node_modules/.pnpm/@oxc-project+runtime@0.80.0/node_modules/@oxc-project/runtime/src/helpers/typeof.js": ((exports, module) => {
|
|
30
|
-
function _typeof$2(o) {
|
|
31
|
-
"@babel/helpers - typeof";
|
|
32
|
-
return module.exports = _typeof$2 = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o$1) {
|
|
33
|
-
return typeof o$1;
|
|
34
|
-
} : function(o$1) {
|
|
35
|
-
return o$1 && "function" == typeof Symbol && o$1.constructor === Symbol && o$1 !== Symbol.prototype ? "symbol" : typeof o$1;
|
|
36
|
-
}, module.exports.__esModule = true, module.exports["default"] = module.exports, _typeof$2(o);
|
|
37
|
-
}
|
|
38
|
-
module.exports = _typeof$2, module.exports.__esModule = true, module.exports["default"] = module.exports;
|
|
39
|
-
}) });
|
|
40
|
-
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
//#region \0@oxc-project+runtime@0.115.0/helpers/typeof.js
|
|
3
|
+
function _typeof(o) {
|
|
4
|
+
"@babel/helpers - typeof";
|
|
5
|
+
return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o) {
|
|
6
|
+
return typeof o;
|
|
7
|
+
} : function(o) {
|
|
8
|
+
return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;
|
|
9
|
+
}, _typeof(o);
|
|
10
|
+
}
|
|
41
11
|
//#endregion
|
|
42
|
-
//#region
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
var
|
|
48
|
-
if (
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
return ("string" === r ? String : Number)(t);
|
|
54
|
-
}
|
|
55
|
-
module.exports = toPrimitive$1, module.exports.__esModule = true, module.exports["default"] = module.exports;
|
|
56
|
-
}) });
|
|
57
|
-
|
|
12
|
+
//#region \0@oxc-project+runtime@0.115.0/helpers/toPrimitive.js
|
|
13
|
+
function toPrimitive(t, r) {
|
|
14
|
+
if ("object" != _typeof(t) || !t) return t;
|
|
15
|
+
var e = t[Symbol.toPrimitive];
|
|
16
|
+
if (void 0 !== e) {
|
|
17
|
+
var i = e.call(t, r || "default");
|
|
18
|
+
if ("object" != _typeof(i)) return i;
|
|
19
|
+
throw new TypeError("@@toPrimitive must return a primitive value.");
|
|
20
|
+
}
|
|
21
|
+
return ("string" === r ? String : Number)(t);
|
|
22
|
+
}
|
|
58
23
|
//#endregion
|
|
59
|
-
//#region
|
|
60
|
-
|
|
61
|
-
var
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
var i = toPrimitive(t, "string");
|
|
65
|
-
return "symbol" == _typeof(i) ? i : i + "";
|
|
66
|
-
}
|
|
67
|
-
module.exports = toPropertyKey$1, module.exports.__esModule = true, module.exports["default"] = module.exports;
|
|
68
|
-
}) });
|
|
69
|
-
|
|
24
|
+
//#region \0@oxc-project+runtime@0.115.0/helpers/toPropertyKey.js
|
|
25
|
+
function toPropertyKey(t) {
|
|
26
|
+
var i = toPrimitive(t, "string");
|
|
27
|
+
return "symbol" == _typeof(i) ? i : i + "";
|
|
28
|
+
}
|
|
70
29
|
//#endregion
|
|
71
|
-
//#region
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
}) : e[r] = t, e;
|
|
81
|
-
}
|
|
82
|
-
module.exports = _defineProperty$2, module.exports.__esModule = true, module.exports["default"] = module.exports;
|
|
83
|
-
}) });
|
|
84
|
-
|
|
30
|
+
//#region \0@oxc-project+runtime@0.115.0/helpers/defineProperty.js
|
|
31
|
+
function _defineProperty(e, r, t) {
|
|
32
|
+
return (r = toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
|
|
33
|
+
value: t,
|
|
34
|
+
enumerable: !0,
|
|
35
|
+
configurable: !0,
|
|
36
|
+
writable: !0
|
|
37
|
+
}) : e[r] = t, e;
|
|
38
|
+
}
|
|
85
39
|
//#endregion
|
|
86
40
|
//#region src/fast-cache.ts
|
|
87
|
-
var import_defineProperty$1 = /* @__PURE__ */ __toESM(require_defineProperty());
|
|
88
41
|
/**
|
|
89
42
|
* 高性能 LRU 缓存实现
|
|
90
43
|
* 使用 Map + 双向链表实现 O(1) 复杂度的所有操作
|
|
91
44
|
*/
|
|
92
45
|
var FastCache = class {
|
|
93
46
|
constructor(maxSize) {
|
|
94
|
-
(
|
|
95
|
-
(
|
|
96
|
-
(
|
|
97
|
-
(
|
|
98
|
-
(
|
|
99
|
-
(
|
|
47
|
+
_defineProperty(this, "cache", void 0);
|
|
48
|
+
_defineProperty(this, "head", void 0);
|
|
49
|
+
_defineProperty(this, "tail", void 0);
|
|
50
|
+
_defineProperty(this, "maxSize", void 0);
|
|
51
|
+
_defineProperty(this, "hits", 0);
|
|
52
|
+
_defineProperty(this, "misses", 0);
|
|
100
53
|
if (maxSize <= 0) throw new Error("Cache size must be positive");
|
|
101
54
|
this.maxSize = maxSize;
|
|
102
55
|
this.cache = /* @__PURE__ */ new Map();
|
|
@@ -109,7 +62,7 @@ var FastCache = class {
|
|
|
109
62
|
const node = this.cache.get(key);
|
|
110
63
|
if (node === void 0) {
|
|
111
64
|
this.misses++;
|
|
112
|
-
return
|
|
65
|
+
return;
|
|
113
66
|
}
|
|
114
67
|
this.moveToHead(node);
|
|
115
68
|
this.hits++;
|
|
@@ -202,36 +155,33 @@ var FastCache = class {
|
|
|
202
155
|
if (lastNode && lastNode !== this.head) this.deleteNode(lastNode);
|
|
203
156
|
}
|
|
204
157
|
};
|
|
205
|
-
|
|
206
158
|
//#endregion
|
|
207
159
|
//#region src/fast-cache-ttl.ts
|
|
208
|
-
var import_defineProperty = /* @__PURE__ */ __toESM(require_defineProperty());
|
|
209
160
|
/**
|
|
210
161
|
* 带 TTL (Time To Live) 支持的高性能缓存实现。
|
|
211
162
|
* 继承自 FastCache,并增加了一个按时间排序的独立链表,
|
|
212
163
|
* 以实现 O(M) 复杂度的过期项目清理(M 为过期数量)。
|
|
213
164
|
*
|
|
214
165
|
* @important 在 Node.js 环境下使用 `autoCleanup: true` 时,
|
|
215
|
-
*
|
|
216
|
-
*
|
|
166
|
+
* 内部定时器在支持的运行时会调用 `unref()`,因此通常不会单独阻止进程退出。
|
|
167
|
+
* 如果缓存生命周期明确,仍建议调用 `destroy()` 主动清理定时器。
|
|
217
168
|
*/
|
|
218
169
|
var FastCacheWithTTL = class extends FastCache {
|
|
219
170
|
constructor(options) {
|
|
220
171
|
super(options.maxSize);
|
|
221
|
-
(
|
|
222
|
-
(
|
|
223
|
-
(
|
|
224
|
-
(
|
|
225
|
-
(
|
|
226
|
-
(0, import_defineProperty.default)(this, "expired", 0);
|
|
172
|
+
_defineProperty(this, "ttl", void 0);
|
|
173
|
+
_defineProperty(this, "cleanupTimer", void 0);
|
|
174
|
+
_defineProperty(this, "timeHead", void 0);
|
|
175
|
+
_defineProperty(this, "timeTail", void 0);
|
|
176
|
+
_defineProperty(this, "expired", 0);
|
|
227
177
|
if (options.ttl !== void 0 && options.ttl <= 0) throw new Error("TTL must be positive");
|
|
228
178
|
this.ttl = options.ttl ?? 0;
|
|
229
|
-
|
|
179
|
+
const autoCleanup = options.autoCleanup ?? false;
|
|
230
180
|
this.timeHead = {};
|
|
231
181
|
this.timeTail = {};
|
|
232
182
|
this.timeHead.timeNext = this.timeTail;
|
|
233
183
|
this.timeTail.timePrev = this.timeHead;
|
|
234
|
-
if (
|
|
184
|
+
if (autoCleanup && this.ttl > 0) {
|
|
235
185
|
const cleanupInterval = options.cleanupInterval ?? this.ttl;
|
|
236
186
|
if (cleanupInterval <= 0) throw new Error("cleanupInterval must be positive");
|
|
237
187
|
this.cleanupTimer = setInterval(() => this.cleanup(), cleanupInterval);
|
|
@@ -243,13 +193,13 @@ var FastCacheWithTTL = class extends FastCache {
|
|
|
243
193
|
const node = this.cache.get(key);
|
|
244
194
|
if (node === void 0) {
|
|
245
195
|
this.misses++;
|
|
246
|
-
return
|
|
196
|
+
return;
|
|
247
197
|
}
|
|
248
198
|
if (this.isExpired(node)) {
|
|
249
199
|
this.delete(key);
|
|
250
200
|
this.expired++;
|
|
251
201
|
this.misses++;
|
|
252
|
-
return
|
|
202
|
+
return;
|
|
253
203
|
}
|
|
254
204
|
return super.get(key);
|
|
255
205
|
}
|
|
@@ -284,27 +234,9 @@ var FastCacheWithTTL = class extends FastCache {
|
|
|
284
234
|
}
|
|
285
235
|
return true;
|
|
286
236
|
}
|
|
287
|
-
get size() {
|
|
288
|
-
return this.cache.size;
|
|
289
|
-
}
|
|
290
|
-
get capacity() {
|
|
291
|
-
return this.maxSize;
|
|
292
|
-
}
|
|
293
|
-
setMany(entries) {
|
|
294
|
-
for (const [key, value] of entries) this.set(key, value);
|
|
295
|
-
}
|
|
296
|
-
getMany(keys) {
|
|
297
|
-
const result = /* @__PURE__ */ new Map();
|
|
298
|
-
for (const key of keys) {
|
|
299
|
-
const value = this.get(key);
|
|
300
|
-
if (value !== void 0) result.set(key, value);
|
|
301
|
-
}
|
|
302
|
-
return result;
|
|
303
|
-
}
|
|
304
237
|
getStats() {
|
|
305
|
-
const stats = super.getStats();
|
|
306
238
|
return {
|
|
307
|
-
...
|
|
239
|
+
...super.getStats(),
|
|
308
240
|
expired: this.expired
|
|
309
241
|
};
|
|
310
242
|
}
|
|
@@ -322,8 +254,7 @@ var FastCacheWithTTL = class extends FastCache {
|
|
|
322
254
|
return removedCount;
|
|
323
255
|
}
|
|
324
256
|
/**
|
|
325
|
-
*
|
|
326
|
-
* 如果开启了 `autoCleanup`,你应当在应用关闭前调用此方法。
|
|
257
|
+
* 清理自动清理定时器,适合在可控生命周期中主动释放资源。
|
|
327
258
|
*/
|
|
328
259
|
destroy() {
|
|
329
260
|
if (this.cleanupTimer) {
|
|
@@ -358,7 +289,6 @@ var FastCacheWithTTL = class extends FastCache {
|
|
|
358
289
|
this._addToTimeListTail(node);
|
|
359
290
|
}
|
|
360
291
|
};
|
|
361
|
-
|
|
362
292
|
//#endregion
|
|
363
293
|
//#region src/index.ts
|
|
364
294
|
function createCache(maxSize) {
|
|
@@ -381,10 +311,9 @@ const CachePresets = {
|
|
|
381
311
|
autoCleanup: true
|
|
382
312
|
})
|
|
383
313
|
};
|
|
384
|
-
|
|
385
314
|
//#endregion
|
|
386
315
|
exports.CachePresets = CachePresets;
|
|
387
316
|
exports.FastCache = FastCache;
|
|
388
317
|
exports.FastCacheWithTTL = FastCacheWithTTL;
|
|
389
318
|
exports.createCache = createCache;
|
|
390
|
-
exports.createCacheWithTTL = createCacheWithTTL;
|
|
319
|
+
exports.createCacheWithTTL = createCacheWithTTL;
|
package/dist/main.mjs
CHANGED
|
@@ -1,15 +1,14 @@
|
|
|
1
|
-
//#region
|
|
1
|
+
//#region \0@oxc-project+runtime@0.115.0/helpers/typeof.js
|
|
2
2
|
function _typeof(o) {
|
|
3
3
|
"@babel/helpers - typeof";
|
|
4
|
-
return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o
|
|
5
|
-
return typeof o
|
|
6
|
-
} : function(o
|
|
7
|
-
return o
|
|
4
|
+
return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o) {
|
|
5
|
+
return typeof o;
|
|
6
|
+
} : function(o) {
|
|
7
|
+
return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;
|
|
8
8
|
}, _typeof(o);
|
|
9
9
|
}
|
|
10
|
-
|
|
11
10
|
//#endregion
|
|
12
|
-
//#region
|
|
11
|
+
//#region \0@oxc-project+runtime@0.115.0/helpers/toPrimitive.js
|
|
13
12
|
function toPrimitive(t, r) {
|
|
14
13
|
if ("object" != _typeof(t) || !t) return t;
|
|
15
14
|
var e = t[Symbol.toPrimitive];
|
|
@@ -20,16 +19,14 @@ function toPrimitive(t, r) {
|
|
|
20
19
|
}
|
|
21
20
|
return ("string" === r ? String : Number)(t);
|
|
22
21
|
}
|
|
23
|
-
|
|
24
22
|
//#endregion
|
|
25
|
-
//#region
|
|
23
|
+
//#region \0@oxc-project+runtime@0.115.0/helpers/toPropertyKey.js
|
|
26
24
|
function toPropertyKey(t) {
|
|
27
25
|
var i = toPrimitive(t, "string");
|
|
28
26
|
return "symbol" == _typeof(i) ? i : i + "";
|
|
29
27
|
}
|
|
30
|
-
|
|
31
28
|
//#endregion
|
|
32
|
-
//#region
|
|
29
|
+
//#region \0@oxc-project+runtime@0.115.0/helpers/defineProperty.js
|
|
33
30
|
function _defineProperty(e, r, t) {
|
|
34
31
|
return (r = toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
|
|
35
32
|
value: t,
|
|
@@ -38,7 +35,6 @@ function _defineProperty(e, r, t) {
|
|
|
38
35
|
writable: !0
|
|
39
36
|
}) : e[r] = t, e;
|
|
40
37
|
}
|
|
41
|
-
|
|
42
38
|
//#endregion
|
|
43
39
|
//#region src/fast-cache.ts
|
|
44
40
|
/**
|
|
@@ -65,7 +61,7 @@ var FastCache = class {
|
|
|
65
61
|
const node = this.cache.get(key);
|
|
66
62
|
if (node === void 0) {
|
|
67
63
|
this.misses++;
|
|
68
|
-
return
|
|
64
|
+
return;
|
|
69
65
|
}
|
|
70
66
|
this.moveToHead(node);
|
|
71
67
|
this.hits++;
|
|
@@ -158,7 +154,6 @@ var FastCache = class {
|
|
|
158
154
|
if (lastNode && lastNode !== this.head) this.deleteNode(lastNode);
|
|
159
155
|
}
|
|
160
156
|
};
|
|
161
|
-
|
|
162
157
|
//#endregion
|
|
163
158
|
//#region src/fast-cache-ttl.ts
|
|
164
159
|
/**
|
|
@@ -167,26 +162,25 @@ var FastCache = class {
|
|
|
167
162
|
* 以实现 O(M) 复杂度的过期项目清理(M 为过期数量)。
|
|
168
163
|
*
|
|
169
164
|
* @important 在 Node.js 环境下使用 `autoCleanup: true` 时,
|
|
170
|
-
*
|
|
171
|
-
*
|
|
165
|
+
* 内部定时器在支持的运行时会调用 `unref()`,因此通常不会单独阻止进程退出。
|
|
166
|
+
* 如果缓存生命周期明确,仍建议调用 `destroy()` 主动清理定时器。
|
|
172
167
|
*/
|
|
173
168
|
var FastCacheWithTTL = class extends FastCache {
|
|
174
169
|
constructor(options) {
|
|
175
170
|
super(options.maxSize);
|
|
176
171
|
_defineProperty(this, "ttl", void 0);
|
|
177
|
-
_defineProperty(this, "autoCleanup", void 0);
|
|
178
172
|
_defineProperty(this, "cleanupTimer", void 0);
|
|
179
173
|
_defineProperty(this, "timeHead", void 0);
|
|
180
174
|
_defineProperty(this, "timeTail", void 0);
|
|
181
175
|
_defineProperty(this, "expired", 0);
|
|
182
176
|
if (options.ttl !== void 0 && options.ttl <= 0) throw new Error("TTL must be positive");
|
|
183
177
|
this.ttl = options.ttl ?? 0;
|
|
184
|
-
|
|
178
|
+
const autoCleanup = options.autoCleanup ?? false;
|
|
185
179
|
this.timeHead = {};
|
|
186
180
|
this.timeTail = {};
|
|
187
181
|
this.timeHead.timeNext = this.timeTail;
|
|
188
182
|
this.timeTail.timePrev = this.timeHead;
|
|
189
|
-
if (
|
|
183
|
+
if (autoCleanup && this.ttl > 0) {
|
|
190
184
|
const cleanupInterval = options.cleanupInterval ?? this.ttl;
|
|
191
185
|
if (cleanupInterval <= 0) throw new Error("cleanupInterval must be positive");
|
|
192
186
|
this.cleanupTimer = setInterval(() => this.cleanup(), cleanupInterval);
|
|
@@ -198,13 +192,13 @@ var FastCacheWithTTL = class extends FastCache {
|
|
|
198
192
|
const node = this.cache.get(key);
|
|
199
193
|
if (node === void 0) {
|
|
200
194
|
this.misses++;
|
|
201
|
-
return
|
|
195
|
+
return;
|
|
202
196
|
}
|
|
203
197
|
if (this.isExpired(node)) {
|
|
204
198
|
this.delete(key);
|
|
205
199
|
this.expired++;
|
|
206
200
|
this.misses++;
|
|
207
|
-
return
|
|
201
|
+
return;
|
|
208
202
|
}
|
|
209
203
|
return super.get(key);
|
|
210
204
|
}
|
|
@@ -239,27 +233,9 @@ var FastCacheWithTTL = class extends FastCache {
|
|
|
239
233
|
}
|
|
240
234
|
return true;
|
|
241
235
|
}
|
|
242
|
-
get size() {
|
|
243
|
-
return this.cache.size;
|
|
244
|
-
}
|
|
245
|
-
get capacity() {
|
|
246
|
-
return this.maxSize;
|
|
247
|
-
}
|
|
248
|
-
setMany(entries) {
|
|
249
|
-
for (const [key, value] of entries) this.set(key, value);
|
|
250
|
-
}
|
|
251
|
-
getMany(keys) {
|
|
252
|
-
const result = /* @__PURE__ */ new Map();
|
|
253
|
-
for (const key of keys) {
|
|
254
|
-
const value = this.get(key);
|
|
255
|
-
if (value !== void 0) result.set(key, value);
|
|
256
|
-
}
|
|
257
|
-
return result;
|
|
258
|
-
}
|
|
259
236
|
getStats() {
|
|
260
|
-
const stats = super.getStats();
|
|
261
237
|
return {
|
|
262
|
-
...
|
|
238
|
+
...super.getStats(),
|
|
263
239
|
expired: this.expired
|
|
264
240
|
};
|
|
265
241
|
}
|
|
@@ -277,8 +253,7 @@ var FastCacheWithTTL = class extends FastCache {
|
|
|
277
253
|
return removedCount;
|
|
278
254
|
}
|
|
279
255
|
/**
|
|
280
|
-
*
|
|
281
|
-
* 如果开启了 `autoCleanup`,你应当在应用关闭前调用此方法。
|
|
256
|
+
* 清理自动清理定时器,适合在可控生命周期中主动释放资源。
|
|
282
257
|
*/
|
|
283
258
|
destroy() {
|
|
284
259
|
if (this.cleanupTimer) {
|
|
@@ -313,7 +288,6 @@ var FastCacheWithTTL = class extends FastCache {
|
|
|
313
288
|
this._addToTimeListTail(node);
|
|
314
289
|
}
|
|
315
290
|
};
|
|
316
|
-
|
|
317
291
|
//#endregion
|
|
318
292
|
//#region src/index.ts
|
|
319
293
|
function createCache(maxSize) {
|
|
@@ -336,6 +310,5 @@ const CachePresets = {
|
|
|
336
310
|
autoCleanup: true
|
|
337
311
|
})
|
|
338
312
|
};
|
|
339
|
-
|
|
340
313
|
//#endregion
|
|
341
|
-
export { CachePresets, FastCache, FastCacheWithTTL, createCache, createCacheWithTTL };
|
|
314
|
+
export { CachePresets, FastCache, FastCacheWithTTL, createCache, createCacheWithTTL };
|
package/package.json
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fast-map-cache",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"description": "High-performance TypeScript LRU cache (with optional TTL) for Node.js & browsers.",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
8
|
+
"type": "commonjs",
|
|
8
9
|
"main": "./dist/main.js",
|
|
9
10
|
"module": "./dist/main.mjs",
|
|
10
11
|
"types": "./dist/main.d.ts",
|
|
@@ -20,8 +21,14 @@
|
|
|
20
21
|
},
|
|
21
22
|
"exports": {
|
|
22
23
|
".": {
|
|
23
|
-
"import":
|
|
24
|
-
|
|
24
|
+
"import": {
|
|
25
|
+
"types": "./dist/main.d.mts",
|
|
26
|
+
"default": "./dist/main.mjs"
|
|
27
|
+
},
|
|
28
|
+
"require": {
|
|
29
|
+
"types": "./dist/main.d.ts",
|
|
30
|
+
"default": "./dist/main.js"
|
|
31
|
+
}
|
|
25
32
|
},
|
|
26
33
|
"./package.json": "./package.json"
|
|
27
34
|
},
|
|
@@ -44,19 +51,21 @@
|
|
|
44
51
|
},
|
|
45
52
|
"license": "MIT",
|
|
46
53
|
"devDependencies": {
|
|
47
|
-
"@changesets/cli": "^2.
|
|
48
|
-
"@commitlint/cli": "^
|
|
49
|
-
"@commitlint/config-conventional": "^
|
|
50
|
-
"@vitest/coverage-v8": "^
|
|
51
|
-
"lint-staged": "^16.
|
|
52
|
-
"oxlint": "^1.
|
|
53
|
-
"pnpm": "^10.
|
|
54
|
-
"prettier": "^3.
|
|
54
|
+
"@changesets/cli": "^2.30.0",
|
|
55
|
+
"@commitlint/cli": "^20.4.4",
|
|
56
|
+
"@commitlint/config-conventional": "^20.4.4",
|
|
57
|
+
"@vitest/coverage-v8": "^4.1.0",
|
|
58
|
+
"lint-staged": "^16.3.3",
|
|
59
|
+
"oxlint": "^1.55.0",
|
|
60
|
+
"pnpm": "^10.32.1",
|
|
61
|
+
"prettier": "^3.8.1",
|
|
62
|
+
"publint": "^0.3.15",
|
|
55
63
|
"simple-git-hooks": "^2.13.0",
|
|
56
|
-
"tsdown": "^0.
|
|
57
|
-
"tsx": "^4.
|
|
58
|
-
"typescript": "^5.
|
|
59
|
-
"
|
|
64
|
+
"tsdown": "^0.21.2",
|
|
65
|
+
"tsx": "^4.21.0",
|
|
66
|
+
"typescript": "^5.9.3",
|
|
67
|
+
"vite": "^8.0.0",
|
|
68
|
+
"vitest": "^4.1.0"
|
|
60
69
|
},
|
|
61
70
|
"simple-git-hooks": {
|
|
62
71
|
"pre-commit": "npx lint-staged",
|
|
@@ -71,7 +80,7 @@
|
|
|
71
80
|
},
|
|
72
81
|
"repository": {
|
|
73
82
|
"type": "git",
|
|
74
|
-
"url": "https://github.com/crper/fast-map-cache.git"
|
|
83
|
+
"url": "git+https://github.com/crper/fast-map-cache.git"
|
|
75
84
|
},
|
|
76
85
|
"bugs": {
|
|
77
86
|
"url": "https://github.com/crper/fast-map-cache/issues"
|