console 内存占用的误解

背景

闲来无事想研究下执行 console 是否会导致内存泄漏,写了个简单的例子运行,看到内存占用确实会因为 console 导致增大。后面在网上搜了下,发现蛮多文章都会提到打开 devtools 才会内存泄漏,不打开就不会,是这样么?先下结论:无论打不打开 devtoolsconsole 都会导致内存占用,但应该不算泄漏。

简单例子

在无痕模式下运行,排除插件等干扰因素

html 复制代码
<html>
  <body>
    <button id="execute">生成并 console</button>
    <div id="msg1"></div>
    <div id="msg2"></div>

    <script>
      // 实时更新内存占用
      setInterval(() => {
        document.querySelector(
          '#msg1'
        ).innerHTML = `<span>实时: totalJSHeapSize=${window.performance.memory.totalJSHeapSize}, usedJSHeapSize=${window.performance.memory.usedJSHeapSize}</span>`;
      }, 1000);

      let counter = 0;
      // 每次执行更新内存占用
      function updateTag() {
        document.querySelector(
          '#msg2'
        ).innerHTML = `<span>执行${counter}: totalJSHeapSize=${window.performance.memory.totalJSHeapSize}, usedJSHeapSize=${window.performance.memory.usedJSHeapSize}</span>`;
      }
      updateTag();

      document.querySelector('#execute').addEventListener('click', () => {
        const records = [];
        for (let i = 0; i < 100000; i++) {
          records.push({});
        }
        console.log(records);

        counter++;
        updateTag();
      });
    </script>
  </body>
</html>

下图 Gif 现象:

  1. 初始化内存占用(totalJSHeapSize) 1,745,973 bytes
  2. 随着执行次数,内存占用越来越高直至 53,572,661
  3. 打开 devtools 后,手动触发 GC,降至 35,656,749
  4. 清空 console 后,再次手动触发 GC,再降到 2,151,469

可以看到内存占用增大是在打开 devtools 之前就发生了,尽管后续手动触发 GC 后占用稍减少,但量级没有变化。而在清空 console 面板之后再次触发 GC 后才恢复初始的量级。

网上例子的误解

html 复制代码
<!DOCTYPE html>
<html lang="en">
  <body>
    <button id="btn">点我</button>
    <div id="box"></div>
    <script>
      const btn = document.getElementById('btn');
      const box = document.getElementById('box');

      btn.addEventListener('click', function () {
        const MB = 1024 * 1024;
        log();

        function log() {
          const memory = performance.memory.totalJSHeapSize;
          const usagedMemory = Math.floor(memory / MB);
          box.insertAdjacentHTML('beforeend', `<span>${usagedMemory} </span>`);

          const obj = { usagedMemory, str: 'g'.repeat(50 * MB) };
          console.log(obj);

          setTimeout(() => log(), 50);
        }
      });
    </script>
  </body>
</html>

作者:zxg_神说要有光 链接:https://juejin.cn/post/7185501830040944698
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

这篇文章中作者给出的例子可以看到两种情况:

  1. 打开 devtools 内存爆炸
  2. 不打开 devtools 内存平稳

评论中有赞同也有疑惑和反对的。其实这里关键在于理清 console 和 devtools 之间的关联:

通俗解释,懂的朋友可以帮忙补充下。

  • 打开 devtools 时,console 会自动解开打印的对象(1 层)
  • 不打开时,console 不会自动解开打印的对象

console.log({a:1,b:{c:2,d:{e:3}}})

不同浏览器可能有不同行为

现在大家心中应该有答案了,其实打开 devtools 之后,由于"自动解开对象"的机制,控制台需要读取并输出大字符串,内存占用自然就会增大;而为什么例子中不打开 devtools 内存没什么变化,其实应该是有变化的,只是可能例子中有几个因素会影响直观:单个对象占用小可能被 Math.floor(n/1024/1024) 舍去;内核对字符串有优化;没有展示其它指标 usedJSHeapSize 等。

小练习,修改网上例子:

const obj = { usagedMemory, str: 'g'.repeat(50 _ MB) };

改成

const obj = { usagedMemory, wrapper: {str: 'g'.repeat(50 _ MB)} };

看下打开 devtools 还会不会炸

结尾

回到结论,确定了 console 会占用内存。那为什么不算泄漏呢,我们要回归 console 的初衷,是用作记录关键日志的,"记"肯定会占用内存(无法白嫖haha)。退一步,如果真的会被垃圾回收,是开发者想要的效果吗?

最后在使用 console 时需要注意:

  1. 尽量不输出大量内容、不直接输出对象
  2. 打包工具配置构建生产环境自动去除 console 语句

感谢阅读,有疑问或者建议欢迎评论或者私信,一起交流学习。

相关推荐
玉米Yvmi4 分钟前
从零理解 CSS 弹性布局:轻松掌控页面元素排布
前端·javascript·css
西洼工作室4 分钟前
前端js汉字手写练习系统
前端·javascript·css
徐同保12 分钟前
n8n+GPT-4o一次解析多张图片
开发语言·前端·javascript
GISer_Jing24 分钟前
AI赋能前端:从核心概念到工程实践的全景学习指南
前端·javascript·aigc
不爱吃糖的程序媛32 分钟前
Flutter-OH OAuth 鸿蒙平台适配详细技术文档
javascript·flutter·harmonyos
前端OnTheRun39 分钟前
如何禁用项目中的ESLint配置?
javascript·vue.js·eslint
前端无涯1 小时前
APP 内嵌 H5 复制功能实现:从现代 API 到兼容兜底方案
javascript
LFly_ice1 小时前
Next-1-启动!
开发语言·前端·javascript
cc蒲公英1 小时前
vue nextTick和setTimeout区别
前端·javascript·vue.js
sinat_384241091 小时前
OpenSpeedy 是一款开源免费的游戏变速工具
javascript