lru-caching
Version:
A high-performance LRU caching implementation with TTL support, batch operations and memory optimization
231 lines (229 loc) • 8.07 kB
TypeScript
/**
* ========================== 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 };