打开 Chrome 的隐身模式,并关闭所有非必要的 Chrome 扩展,避免缓存和 Chrome 插件内存占用造成的影响
查看网页内存配额及消耗
window.performance.memory
使用 Performance 可视化检测内存泄漏
在 Chrome DevTools 的 Performance 面板勾选 Memory 并开启记录,之后在页面上执行一些操作。我们在记录数据的开始和结束时刻都手动进行一次 GC。
在结果图表中 HEAP 这一栏查看内存的使用情况,我们将一开始没有进行操作时的内存使用情况作为基准值,与最后停止操作并进行 GC 后的值进行比较,如果有较明显的差距,则说明产生了内存泄漏。
在Memory面板进一步分析内存泄露问题
使用内存堆快照检测分离的 DOM 内存泄漏
游离的DOM节点
一个 DOM 节点只有在没有被引用时才会被 GC,当 DOM 节点不在 DOM 树中,但是却被 JS 代码保留着引用,这种情况下会造成内存泄漏。
查看内存分配时间轴信息
在 Memory 面板选择 Allocation instrumentation on timeline 可以记录内存分配时间轴信息。Chrome 会周期性以一定的间隔记录内存堆快照,并在记录结束时进行最后一次快照,以此生成内存分配时间轴信息。如果较早时间分配的对象依然大量存活,则说明可能有内存泄漏的问题。
评估不同代码造成的内存消耗
图片存储对比
同时发送10张2M左右的高清图,发现在收到消息时,使用createObjectURL内存增长大概3k,使用base64内存增长大概2M
图片存储:Object URL vs base64
假设blob占用内存为n
| 存储形式 | blob是否被回收 | 占用内存 | 是否可跨会话使用 |
|---|---|---|---|
| Object URL | 否 | n | 否 |
| base64 | 是 | 1.33n | 是 |
Object URL跨会话使用
- blob存储在IndexDB中,需要跨会话使用时,从IndexDB拿原始文件使用
// 假设 blob 是你获取到的 Blob 数据
const storeBlob = async (blob) => {
const db = await openDB('my-database', 1, {
upgrade(db) {
db.createObjectStore('blobs');
},
});
await db.put('blobs', blob, 'myBlobKey');
};
const getBlobFromDB = async () => {
const db = await openDB('my-database', 1);
return await db.get('blobs', 'myBlobKey');
};
const blobToBase64 = (blob) => {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onloadend = () => {
resolve(reader.result);
};
reader.onerror = reject;
reader.readAsDataURL(blob);
});
};
const convertStoredBlobToBase64 = async () => {
const blob = await getBlobFromDB();
if (blob) {
const base64 = await blobToBase64(blob);
console.log(base64);
return base64;
} else {
console.log('No Blob found in storage');
}
};
- 从Object URL提取blob ,转为base64
async function fetchBlobFromObjectURL(objectURL) {
const response = await fetch(objectURL);
const blob = await response.blob();
return blob;
}
function blobToBase64(blob) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onloadend = () => {
resolve(reader.result);
};
reader.onerror = reject;
reader.readAsDataURL(blob);
});
}
async function objectURLToBase64(objectURL) {
try {
const blob = await fetchBlobFromObjectURL(objectURL);
const base64 = await blobToBase64(blob);
return base64;
} catch (error) {
console.error('Error converting Object URL to Base64:', error);
return null;
}
}
// 使用示例
const objectURL = URL.createObjectURL(new Blob(['example content'], { type: 'text/plain' }));
objectURLToBase64(objectURL).then(base64 => {
console.log(base64);
});