UNPKG

lru-caching

Version:

A high-performance LRU caching implementation with TTL support, batch operations and memory optimization

231 lines (229 loc) 8.07 kB
/** * ========================== 1. Entry 相关定义(类型安全与性能基础)========================== * 用数组存储节点 + 枚举索引,替代对象 Entry: * 1. 数组索引访问比对象属性快 3-5 倍(无哈希计算/原型链开销) * 2. 枚举消除魔法数字,TypeScript 下自动提示,避免索引错误 */ declare enum EntryIndex { KEY = 0,// 缓存键(string | number) VALUE = 1,// 缓存值(泛型 T) NEXT = 2,// 下一个节点指针(Entry<T> | null) PREV = 3,// 上一个节点指针(Entry<T> | null) EXPIRE = 4 } /** * 数组型节点类型定义 * @template T - 缓存值的类型 */ type Entry<T> = [ string | number, T, // EntryIndex.VALUE Entry<T> | null, // EntryIndex.NEXT Entry<T> | null, // EntryIndex.PREV number | null ]; /** * ========================== 2. 双向链表(缓存顺序管理核心)========================== * 功能:维护缓存节点的访问顺序(最近使用放尾部,最久未使用放头部) * 优化点: * 1. 哨兵节点(_head/_tail)消除边界判断(无需判断节点是否为头/尾) * 2. 局部缓存频繁访问属性(如 tail.prev),减少重复数组索引查找 * 3. 提供 forEach 方法支持外部安全遍历 */ declare class LinkedList<T> { /** 哨兵头节点(不存储实际数据,仅用于简化边界判断) */ private _head; /** 哨兵尾节点(不存储实际数据,仅用于简化边界判断) */ private _tail; /** 链表长度(缓存节点总数,不含哨兵) */ private _len; constructor(); /** * 插入节点到链表尾部(标记为“最近使用”) * @param entry - 待插入的节点 */ insertEntry(entry: Entry<T>): void; /** * 从链表中移除指定节点 * @param entry - 待移除的节点 */ remove(entry: Entry<T>): void; /** * 将节点移动到链表尾部(标记为“最近使用”) * @param entry - 待移动的节点 */ moveToTail(entry: Entry<T>): void; /** * 获取“最久未使用”的节点(头哨兵的下一个节点) * @returns 最久未使用的节点,链表为空时返回 null */ getLRUEntry(): Entry<T> | null; /** * 获取链表长度(缓存节点总数) * @returns 链表长度 */ len(): number; /** * 清空链表(仅保留哨兵节点) */ clear(): void; /** * 遍历链表所有节点(安全遍历,避免修改节点导致的循环错误) * @param cb - 遍历回调(参数为当前节点) */ forEach(cb: (entry: Entry<T>) => void): void; } /** * ========================== 5. LRU 主类(对外核心 API)========================== * 核心功能:LRU 缓存策略实现,支持 TTL 过期、批量操作、资源释放回调、统计监控 */ declare class LRU<T> { /** 缓存节点的顺序管理链表 */ private _list; /** 键到节点的映射(O(1) 查找) */ private _map; /** 缓存的最大容量(节点总数上限) */ private _maxSize; /** 节点池(复用淘汰节点) */ private _nodePool; /** 节点池容量调整周期(ms) */ private _poolAdjustInterval; /** 节点池调整定时器 */ private _adjustTimer; /** 过期节点检查周期(ms) */ private _expireCheckInterval; /** 过期检查定时器 */ private _expireTimer; /** 节点淘汰时的回调(用于释放资源,如纹理、句柄) */ private _onEvict?; /** 轻量化统计数据 */ private _stats; /** 统计批量更新阈值(每 100 次操作同步到 total) */ private static readonly BATCH_SIZE; /** * 构造函数 * @param maxSize - 缓存最大容量(必须 ≥1) * @param initialPoolRatio - 节点池初始容量占缓存容量的比例(默认 0.5) * @param poolAdjustInterval - 节点池容量调整周期(默认 30000ms = 30s) * @param expireCheckInterval - 过期节点检查周期(默认 5000ms = 5s) * @param onEvict - 节点淘汰时的回调(可选,用于释放资源) */ constructor(maxSize: number, initialPoolRatio?: number, poolAdjustInterval?: number, expireCheckInterval?: number, onEvict?: (key: string | number, value: T) => void); /** * -------------------------- 私有方法:定时器管理 -------------------------- */ /** * 启动节点池容量调整定时器 * 优化逻辑:基于“池复用率”动态调整容量,步长自适应(偏差越大,步长越大) */ private _startPoolAdjustTimer; /** * 启动过期节点检查定时器 * 优化逻辑:批量收集过期节点 → 批量清理,减少重复的 remove/delete 调用 */ private _startExpireTimer; /** * -------------------------- 私有方法:节点管理 -------------------------- */ /** * 获取节点(优先从池复用,无则新建) * @param val - 缓存值 * @param key - 缓存键 * @param ttl - 过期时间(ms,可选) * @returns 可用的节点 */ private _acquireEntry; /** * -------------------------- 公有方法:核心缓存操作 -------------------------- */ /** * 插入/更新缓存 * @param key - 缓存键 * @param value - 缓存值 * @param ttl - 过期时间(ms,可选,null 表示永不过期) * @returns 被淘汰的节点值(缓存满时),无淘汰则返回 null */ put(key: string | number, value: T, ttl?: number): T | null; /** * 获取缓存值 * @param key - 缓存键 * @returns 缓存值(存在且未过期),否则返回 undefined */ get(key: string | number): T | undefined; /** * 删除指定缓存键 * @param key - 缓存键 * @returns 被删除的缓存值,键不存在则返回 null */ delete(key: string | number): T | null; /** * -------------------------- 公有方法:批量操作 -------------------------- */ /** * 批量插入/更新缓存 * @param entries - 批量缓存数据(数组,每个元素含 key/value/ttl) * @returns 被淘汰的缓存值数组 */ batchPut(entries: Array<{ key: string | number; value: T; ttl?: number; }>): T[]; /** * 批量删除缓存键 * @param keys - 待删除的缓存键数组 * @returns 被删除的缓存值数组 */ batchDelete(keys: (string | number)[]): T[]; /** * -------------------------- 公有方法:辅助操作 -------------------------- */ /** * 遍历所有缓存节点(安全遍历,支持读取键/值/过期时间) * @param cb - 遍历回调(参数:key, value, expireTime) */ forEach(cb: (key: string | number, value: T, expireTime?: number) => void): void; /** * 清空所有缓存 */ clear(): void; /** * 获取当前缓存容量(节点总数) * @returns 缓存容量 */ len(): number; /** * 检查缓存是否包含指定键(并判断是否过期) * @param key - 缓存键 * @returns 存在且未过期返回 true,否则返回 false */ has(key: string | number): boolean; /** * 获取缓存统计信息(命中率、操作次数、节点池状态) * @returns 统计信息对象 */ getStats(): Readonly<{ get: { total: number; hit: number; hitRate: number; }; put: { total: number; evict: number; expire: number; }; pool: { size: number; maxSize: number; }; }>; /** * 销毁缓存(清理定时器、释放内存,避免内存泄漏) */ dispose(): void; } export { type Entry, EntryIndex, LinkedList, LRU as default };