【程序员日记】一行console.log引发的血案

🛫 导读

需求

最近公司使用electron中出现内存泄漏的情况。经过n天的努力,最后定位到console.log的问题。
这好像不是第一次遇到类似的问题,特此记录,以敬后效。

开发环境

版本号描述
文章日期2023-11-04
操作系统Win10 - 22H219045.3570

1️⃣ 艰难的排查过程

1. 程序闪退

开发过程中程序一切运行正常,到了测试那里,出现崩溃情况。
多次尝试发现半个小时左右就崩溃了,多个电脑都是这样的。

2. 确定为内存泄漏

一开始一直以为是自己开发的node模块代码异常,导致崩溃。
后来看了下任务管理器的内存,发现某个render进程内存螺旋式上升,积累到半个小时候就崩溃了。
结论:

  • 内存泄漏导致崩溃
  • 大概率不是node模块导致的,因为是render进程不断的增大。

3. 误入歧途

排查问题最笨的思路就是注释代码。由于各种原因,我们也是这条路排查的。
当我们注释掉某封包逻辑后发现一切运行正常。于是猜测是封包的库导致的问题,当即想的是换个库试试。

4. 二分法注释代码

后来某大佬说,可能是用法不对,逐步注释代码试试。然后二分法注释代码,最后在WebSocket的某回调函数内发现,注释了console.log,让一切恢复正常了。

5. 猿脑猜想

该代码会将接受的内容(3Mb左右的对象)打印出来,最后发现该对象未被释放。至于为何未释放,这里也只留下几个猜想:

  • WebSocket回调函数对该对象进行了引用,导致GC不能释放。
  • WebSocket回调函数对该对象进行了缓存(方便后续调用),缓存队列巨大(上千的长度),chrome内存是有上限的(各个版本不一样的,我们用的x86的,据说在2G左右),达到上限的时候,还未出发其内存回收。

2️⃣ 排查

procexp.exe

作为专业的windows工具procexp.exe,提供了查看内存变换的功能,我们可以通过它看到一些内存上的规律。
小编遇到的问题,可以在这上面发现,每2秒,内存增加3Mb左右。这个大小刚好是我们传递的某个对象,通过它能快速定位问题。

procexp.exe默认没有显示Private Delta Bytes选项,我们通过下面的步骤打开该列。

  1. 右键表头,打开对话框
    在这里插入图片描述
    2.选择Process Memory标签页,然后选择Private Delta Bytes选项
    在这里插入图片描述
  • 模拟内存增长:
    如下图,不断的执行window.___=[]; ___.push(new Array(2*1000*1000));,可以查看到内存增长!
    在这里插入图片描述

ps: windows自带的任务管理器也有类似的功能(貌似win11后的某个新版本才有的)。

Performance 和 Memory

这个操作就很专业了,具体细节很多,小编发现一篇很不错的文章:《console.log 一定会导致内存泄漏? 》https://juejin.cn/post/7185501830040944698,这里就不画蛇添足了,有兴趣的直接看该文章即可。

3️⃣ 剔除生产环境中的console.log

webpack插件terser-webpack-plugin

erser-webpack-plugin 是一个 Webpack 的插件,它主要用于对 JavaScript 代码进行压缩和优化。
它通过使用 Terser 这个 JavaScript 压缩库,来实现对 JavaScript 代码的压缩和优化。Terser 是一个非常强大的压缩库,它能够减小 JavaScript 代码的体积,并提高代码的运行效率。

terser-webpack-plugin 插件的使用非常简单,只需要在 Webpack 的配置中添加这个插件,并设置相关的选项即可。可以进行如下配置,保证生成环境中不包含console系列函数:

module.exports = {
  optimization: {
    minimizer: [
      new TerserPlugin({
        terserOptions: {
          // 你的压缩选项
          compress: {
            // drop_console为true时,将删除所有console的函数
            drop_console: process.env.NODE_ENV==='production',
            drop_debugger: true,
            pure_funcs: ["console.log", "console.warn"]
          }
        }
      }),
    ],
  },
};

🛬 文章小结

首先,我们需要明确一点,console.log 本身并不会造成内存泄漏。内存泄漏是指在程序运行过程中,一些不再需要的对象或资源仍然被占用,导致内存无法被释放,从而导致程序运行缓慢或崩溃。

我们来分析一下可能导致内存泄漏的原因。主要有以下几种可能:

  • 闭包:如果在 console.log 中使用了闭包,并且该闭包中引用了外部的变量或对象,那么这些变量或对象就不会被垃圾回收器回收,从而导致内存泄漏。
  • 对象池:如果在代码中使用了对象池技术,例如Pool 或cache,那么这些对象可能会被长期占用,从而导致内存泄漏。
  • 循环引用:如果在代码中存在两个或多个对象之间的循环引用,例如A引用了B,B引用了A,那么这些对象就不会被垃圾回收器回收,从而导致内存泄漏。

综上所述,console.log 本身并不会造成内存泄漏。但是,如果在代码中使用了不当的闭包、对象池或循环引用,那么这些因素可能会导致内存泄漏。
因此,在编写代码时,我们需要注意避免这些问题,以保证程序的稳定性和性能。而且尽可能的别让 console.log 上生产!

📖 参考资料

ps: 文章中内容仅用于技术交流,请勿用于违规违法行为。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

夜猫逐梦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值