为了获取生产环境报错对应的源码位置,之前将打包之后的 map 文件上传到 node 服务,日积月累之下,已经占用了好几个 g 的磁盘空间
就想到用 LRU 算法
的思想去对这些文件进行管理
LRU
LRU
英文全称是 Least Recently Used,最不经常使用,是一种内存管理算法。可以参考 leetcode
的描述 LRU缓存机制
核心思想是 “如果数据最近被访问过,那么将来被访问的几率也更高”。所以在容量有限的情况下,淘汰最近最少使用的缓存。即近期内最不会被访问的数据进行淘汰
可以使用一个队列来缓存数据
如果有新数据插入,就移出队列中最后一个缓存
如果有数据访问,要将访问到的数据移到尾部,重新进行排序
实现
在 javascript
中,可以使用 Map
或者 Set
来模拟一个队列
import path from "path";
import fse from "fs-extra";
/** 上传 sourcemap 存放地址 */
export const sourcemapFilePath = path.join(__dirname, "../../../../uploads");
// 使用 LRU 算法去控制 sourcemap 文件
export class SourcemapCache {
private path = path.join(__dirname, "cache.json");
private length: number; // 最大缓存数量
private cache: Set<string>;
constructor(length = 10) {
this.length = length;
this.cache = new Set(this.readCache() || []);
}
private readCache = () => {
try {
return fse.readJSONSync(this.path);
} catch (error) {
return;
}
};
private saveCache(date: string[]) {
fse.ensureFile(this.path).then(() => {
fse.writeJSONSync(this.path, date);
});
}
private delete(key: string) {
fse.remove(path.resolve(sourcemapFilePath, key));
}
// 访问 缓存中的某一项
access(key: string) {
if (this.cache.has(key)) {
this.cache.delete(key);
this.cache.add(key);
this.saveCache([...this.cache.keys()]);
}
}
// 数据插入,重新排序
put(key: string) {
const keys = [...this.cache.keys()];
// 已存在队列,则移到尾部
if (this.cache.has(key)) {
this.access(key);
} else {
if (keys.length >= this.length) {
const oldestKey = keys[0];
this.cache.delete(oldestKey);
this.delete(oldestKey);
}
this.cache.add(key);
this.saveCache([...this.cache.keys()]);
}
}
}