首页 > 解决方案 > 为什么 chrome 任务管理器内存占用显着增加(170mb)仅在一个 div 的 innerHTML 中呈现 10mb 字符串?

问题描述

我做了一个小测试,在单击按钮时创建了一个 10mb 的字符串。然后在第二个按钮上单击我在 div 的 innerHTML 中呈现该字符串内容。

编码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Test</title>

</head>
<body>
    <button id="btn-load">Load string</button>
    <button id="btn-render">Render string</button>
    <div id="place-to-render"></div>
    <script type="module" src="main.js"></script>
</body>
</html>

JS main.js:

let data;
function createBigString() {
    data = new Array(10000000).join('x'); //10mb
    console.log('created object',data);
}

function render() {
    const placeToRender = document.getElementById('place-to-render');
    placeToRender.innerHTML = data;
    console.log('rendered');
}
document.getElementById('btn-load').addEventListener('click', createBigString);
document.getElementById('btn-render').addEventListener('click', render);

如本答案所述

内存占用列与任务管理器或活动监视器中进程的内存列报告的 MB 数相匹配。

这意味着从操作系统获取的实际 RAM 用于 chrome 上的这个特定选项卡。在chrome任务管理器中可以看到。

我做的记忆测试(隐身):

data在创建字符串(并将其分配给全局变量)后,我记录了堆快照。

然后我点击渲染字符串按钮,在字符串加载到屏幕后,我拍摄了另一个快照。

问题:

标签: javascriptperformancememory-leaksgoogle-chrome-devtoolsv8

解决方案


为什么尽管字符串的大小只有 10mb,但内存占用却有如此大的飞跃?

在屏幕上绘制一个包含 1000 万个字符的字符串所需的像素需要远远超过 10 MB。

除了 JS 内存 + 媒体文件 + DOM 节点的总和之外,内存 FP 究竟包含什么?

整个渲染器进程的内存。在我的脑海中,包括各种库、字体、作为渲染过程结果的“图片”,以及用于正在进行的任务的各种临时内存。

不幸的是,我不知道有任何文档或工具可以了解更多关于这些细节的信息;当然,这并不意味着不存在(参见例如 wOxxOm 的评论)。

为什么实时 JS 的第二个快照从 10mb 变为 1mb,如果值仍然保存在全局数据变量中,因此 GC 不应该清理它,对吗?

是的,GC 没有收集字符串。字符串的后备存储(即实际字符)可以在 V8 和 Blink 之间来回传递。在这种情况下,显然字符内容被转移到了 Blink 的责任,因此它们不再是 JavaScript 堆的一部分(尽管StringJS 堆上的对象仍然引用它们),但它们仍然是整个过程的一部分内存占用。


推荐阅读