HarmonyOS 7 ArkWeb缓存越来越大:按条数限制不够,怎样按字节淘汰资源

HarmonyOS 7 ArkWeb缓存越来越大:按条数限制不够,怎样按字节淘汰资源
缓存只有20个条目,也可能占满内存,因为一个条目可能是几十字节,也可能是几十兆。排查网页资源缓存时,先看字节预算,再看数量。下面实现的是应用自管缓存,不修改ArkWeb内核缓存。
适配范围
size是适配层给出的实际预算估计,不是字符串length。网络压缩大小不等于解码后内存大小。实现只统计缓存持有值,不能证明浏览器或GPU总内存已经受控;还要检查页面、图片解码和响应对象的引用。
案例一
读取a后插入c:a是最近使用项,b应淘汰,最终字节数不超10。
案例二
单个资源超过整个预算:直接不缓存;替换a时先扣除旧大小,避免预算累计错误。
可以运行的实现
export class ByteCache {
entries = new Map(); bytes = 0;
constructor(limit) { if (!Number.isFinite(limit) || limit <= 0) throw Error('limit'); this.limit = limit; }
get(key) { const v=this.entries.get(key); if(!v)return null; this.entries.delete(key);this.entries.set(key,v);return v.value; }
set(key,value,size) {
if(!Number.isFinite(size)||size<0)throw Error('size');
const old=this.entries.get(key);if(old){this.bytes-=old.size;this.entries.delete(key);}
if(size>this.limit)return false;
while(this.bytes+size>this.limit){const first=this.entries.keys().next().value;this.bytes-=this.entries.get(first).size;this.entries.delete(first);}
this.entries.set(key,{value,size});this.bytes+=size;return true;
}
}
复现与断言
把实现与以下测试放进同一个example.mjs,执行node example.mjs。断言失败会报错,全部通过正常退出。这些断言已经在本地Node.js执行;它们不代表SDK编译、真机接口调用或性能实测已经通过。
import assert from 'node:assert/strict';
const cache = new ByteCache(10);
cache.set('a','A',4);cache.set('b','B',4);cache.get('a');cache.set('c','C',4);
assert.equal(cache.get('b'),null);assert.equal(cache.get('a'),'A');assert.equal(cache.bytes,8);
assert.equal(cache.set('large','X',11),false);assert.equal(cache.bytes,8);
cache.set('a','new',2);assert.equal(cache.bytes,6);
assert.throws(()=>cache.set('bad','x',-1));
方案取舍
数量上限简单,却无法控制大资源;FIFO不考虑最近访问;按字节LRU适合大小差别很大的资源。它会扫描淘汰项,但每项在每次淘汰中只删除一次。
接入时别漏掉这些边界
size是适配层给出的实际预算估计,不是字符串length。网络压缩大小不等于解码后内存大小。实现只统计缓存持有值,不能证明浏览器或GPU总内存已经受控;还要检查页面、图片解码和响应对象的引用。
复用时把输入获取与纯逻辑分开:界面、系统事件和服务请求负责取得真实输入,独立模块负责给出判断或保存状态。保留上述两个案例作为回归测试,并对失败原因记录最少必要日志,不记录文件内容、账号凭据或其它敏感数据。升级SDK后重新核对支持设备、接口版本与错误行为,而不是只改目标版本号。
官方资料
示例验证环境为Node.js,验证范围是应用侧逻辑。本文不将示例当作系统接口接入代码;具体接口的支持设备、最低版本和调用方式,以所用SDK对应的官方文档为准。
更多推荐
所有评论(0)