console

lxf2023-03-16 08:56:01

许多前面都会用 console.log 调节,先不说调节高效率如何,最先 console.log 有一个致命性的难题:也会导致内存泄漏。

为什么这样说呢?

用 Performance 和 Memory 专用工具分析一下就明白了。

我们准备这样一段编码:

console

一个按键,点一下以后创建一个二维数组,实行一些测算。

比较常见的逻辑性。

大家最终加了一个 console.log 打印出了一下这一二维数组。

起一个静态数据服务项目

console

浏览器登录

console

点一下 performance 中的垃圾分类回收按键,手动式开启一次 GC:

console

启用 Memory,然后就拍摄,点一下 3 次按键,再执行一次 GC:

console

你就会发现运行内存是这样子的:

console

cpu占用有三次提高,只要我们点一下三次按键的时候就会建立 3 次大二维数组。

不过最后大家手动式 GC 以后并没下降下来,其实就是这个小二维数组没被回收利用。

按道理说,执行命令完,那用的运行内存就需要被释放,随后再执行其他编码,结论这一段执行命令完以后大二维数组仍然占据了运行内存,那样其他编码再执行时可用内存也就少了。

这便是出现了内存泄漏,其实就是执行命令完后不增加内存的恶意程序。

有朋友说,仅仅那么一点运行内存没什么问题呀,总之可用内存还有很多。

但是如果你的代码要跑很长一段时间,这一段编码要实行好多次呢?

每一次实行都是会占有一部分运行内存不释放出来,慢慢地运行内存就不够用了,甚至会导致程序崩溃。

例如当这一段执行命令个 9 次,cpu占用就增加了 9 一个大二维数组的运行内存:

console

再好实行几回呢?

是否就会有奔溃的隐患了。

那为啥说成 console.log 造成的呢?

我们来看一下无需 console.log 是怎么样的:

console

注释掉 console.log,再次跑。

你就会发现现今内存分配状况是这样子的:

console

分派了三次运行内存,可是 GC 后又落下了。

这才是真正并没有内存泄漏好编码。

那为啥 console.log 也会导致内存泄漏呢?

由于控制面板打印目标,你是否有可能会进行看?那么如果这一目标在内存中没了,肯定就看不到了?

因此有这种引入在,电脑浏览器不容易将你打印对象内存优化掉。

许多学生说,那么我不打开控制面板,肯定就没有那个引用了?

答案是否定的:

console

我点一下了几次后,打开控制面板,依旧是能够看见这一对象,表明没被 GC。

换句话说用 console.log 打印出目标的代码一定是有内存泄漏的。

自然,也不仅仅是 console.log 也会导致内存泄漏,还有其他的 4 个原因:

  • 计时器用掉并没有消除,那每一次实行都是会多一个计时器的cpu占用,这便是内存泄漏
  • 原素从 dom 移除开,但是还是有一个自变量引入着他,这种分散的 dom 原素不会被回收利用。每运行一次编码,便会空出分散的 dom 元素运行内存,那也是内存泄漏
  • 闭包引用了某一自变量,这一自变量不被回收利用,如果是这样的闭包较多,那每一次实行都是会空出那些被引用变量的cpu占用。那样引入大对象闭包得多以后,也会造成内存问题
  • 局部变量,这一原本也不会被 GC,需要注意局部变量的应用

总而言之,局部变量、闭包提及的自变量、被删除的 dom 依然被引入、计时器用完了没消除、console.log 都会出现执行命令完后,但是还占有着一部分运行内存的恶意程序,其实就是内存泄漏。

留意,这儿是指应用完成后并没有回收利用,使用阶段的运行内存提高是正常。

那怎么排查呢?

performance 专用工具就能:

console

点一下内存分配状况某个点,便会定位到 performance 里的某一每日任务的代码,点一下能够在下文见到详细信息:

console

这个就精准定位到释放内存的代码,分析一下哪儿会出现难题就可以。

自然,前提条件还是得实行先 GC,继续做一些实际操作,再 GC 这个步骤。

这是从编码视角来剖析内存泄漏,实际上也可以从内存中目标的视角,这一是由 Memory 专用工具:

console

先 GC,拍摄一次运行内存快照更新,再点击几回按键,随后 GC,再拍摄一次运行内存快照更新。

步骤和用 performance 讲解的情况下一样。

取得2次运行内存快照更新是可以判断出有内存泄漏的:

console

能够看见 GC 后cpu占用仍然增加了。

快照更新记录了这个时刻内存中全部对象情况:

console

比照2次快照更新,就能找到转变的那一部分:

console

例如此刻能够看见较大的存储空间提高是 array 目标:

console

之后就可以从 array 的角度去思考是什么导致的内存泄漏了。

除此之外,memory 也有实时分析的一种手段:

console

挑选第二个,随后点几回按键:

console

其实没必要手动式 GC,JS 模块也会做 GC。

除掉 console.log 再拍摄是这样子的:

console

除开最初局部变量会配置一些运行内存之外,点击图标以后的运行内存变蓝之后又变灰了,其实就是被 GC 了。

那样你点几回按键,cpu占用也没有提高。

这便是执行命令完,会回收利用全部需要用到的运行内存好编码。

而前面的那个就是每一次执行命令,都是会占有一部分运行内存不释放出来的内存泄漏编码。

你也可以看到每一次内存分配的对象是啥:

console

无论要用 Performance 专用工具或是 Memory 专用工具,都能够发觉 console.log 有内存泄漏问题。因此还是最好不要用这一来调节了。

的话应该用什么?

用 debugger 呀,不论是 vscode debugger 或是 chrome devtools 的都能够:

console

你可以添加一个 logpoint 代替 console.log 打印出:

console

执行命令到这儿便会打印出:

console

而你的编码里不用写 console.log。

除此之外,好多地方能用中断点取代打印出:

console

能够看见执行命令路线和修饰符,难道不是更有效?

汇总

console.log 也会导致内存泄漏,其实就是执行命令完后,却还占据了一部分运行内存的恶意程序。

除开 console.log,分散的 dom 被自变量引入、局部变量、自变量被闭包引入、计时器没消除也会造成内存泄漏。

我们可以通过 Performance 工具 Memory 专用工具剖析内存泄漏。

先手动式 GC,随后实行一些实际操作,再 GC,假如运行内存并没有返回实行前,就证明这一段编码有内存泄漏,能够再换 Performance 定位到编码部位剖析编码。

Memory 专用工具是以运行内存对象角度而言,能够对2次快照更新做 diff,看看是什么目标泄露了。

还可以实时监测cpu占用状况,看看是不是存有内存泄漏,目标是什么。

console.log 调节高效率也不是很高,能够换为 logpoint,或是打断点。

千万别把 console.log 上生产制造!要不然这种有内存泄漏的代码,一旦实行时间长了会出现难题。

实际上一般新项目也还好,不容易长期性跑,可是相近大屏幕新项目这类长期性跑得,一旦有内存泄漏,一定会奔溃,仅有时间的长短的差别。

(本文有点儿不正确,在续篇更改了:console.log 一定也会导致内存泄漏?不打开 devtools 也就不会)