js删除节点的方法(JSfor循环删除指定节点)

内存管理

V8 内存限制

限制大小

64 位为 1.4GB,32 位为 0.7GB

限制原因

V8 之所以限制了内存的大小,表面上的原因是 V8 最初是作为浏览器的 JavaScript 引擎而设计,不太可能遇到大量内存的场景,而深层次的原因则是由于 V8 的垃圾回收机制的限制。由于 V8 需要保证 JavaScript 应用逻辑与垃圾回收器所看到的不一样,V8 在执行垃圾回收时会阻塞 JavaScript 应用逻辑,直到垃圾回收结束再重新执行 JavaScript 应用逻辑,这种行为被称为“全停顿”(stop-the-world)。若 V8 的堆内存为 1.5GB,V8 做一次小的垃圾回收需要 50ms 以上,做一次非增量式的垃圾回收甚至要 1 秒以上。这样浏览器将在 1s 内失去对用户的响应,造成假死现象。如果有动画效果的话,动画的展现也将显著受到影响。

V8 垃圾回收策略

  • 采用分代回收的思想
  • 内存分为新生代、老生代
  • 针对新、老生代采用不同算法来提升垃圾回收的效率

新生代的对象为存活时间较短的对象,老生代中的对象为存活时间较长或常驻内存的对象。

V8 新生代、老生代内存大小

V8 引擎的新生代内存大小 32MB(64 位)、16MB(32 位),老生代内存大小为 1400MB(64 位)、700MB( 32 位)。

新生代对象回收实现

  • 回收过程采用复制算法+标记整理
  • 新生代内存区被等分为两个空间
  • 使用空间为 From,空闲空间为 To
  • 标记整理后将活动对象拷贝至 To
  • From 和 To 交换空间完成释放

js删除节点的方法(JSfor循环删除指定节点)

惰性清理

由于标记完成后,所有的对象都已经被标记,不是死对象就是活对象,堆上多少空间格局已经确定。我们可以不必着急释放那些死对象所占用的空间,而延迟清理过程的执行。垃圾回收器可以根据需要逐一清理死对象所占用的内存空间

其他

V8 后续还引入了增量式整理(incremental compaction),以及并行标记和并行清理,通过并行利用多核 CPU 来提升垃圾回收的性能

监控内存

内存问题的外在表现

  • 页面出现延迟加载或经常性暂停: 可能存在频繁当 GC 操作,存在一些代码瞬间吃满了内存。
  • 页面出现持续性的糟糕性能: 程序为了达到最优的运行速度,向内存申请了一片较大的内存空间,但空间大小超过了设备所能提供的大小。
  • 页面使用随着时间延长越来越卡:可能存在内存泄漏。

界定内存问题的标准

  • 内存泄漏:内存使用持续升高
  • 内存膨胀:在多数设备上都存在性能问题
  • 频繁垃圾回收:通过内存变化时序图进行分析

监控内存方式

任务管理器

这里以 Google 浏览器为例,使用 Shift + Esc 唤起 Google 浏览器自带的任务管理器

  • Memory(内存) 列表示原生内存。DOM 节点存储在原生内存中。如果此值正在增大,则说明正在创建 DOM 节点。
  • JavaScript Memory(JavaScript 内存) 列表示 JS 堆。此列包含两个值。您感兴趣的值是实时数字(括号中的数字)。实时数字表示您的页面上的可到达对象正在使用的内存量。如果此数字在增大,要么是正在创建新对象,要么是现有对象正在增长。

模拟内存泄漏

在任务管理器里可以看到 JavaScript 内存持续上升

document.body.innerHTML = `<button id="add">add</button>`;document.getElementById('add').addEventListener('click', function (e) {  simulateMemoryLeak();});let result = [];function simulateMemoryLeak() {  setInterval(function () {    result.push(new Array(1000000).join('x'));    document.body.innerHTML = result;  }, 100);}

Timeline 记录内存

这里以 Google 浏览器为例,使用 F12 开启调式,选择 Performance,点击 record(录制),进行页面操作,点击 stop 结束录制之后,开启内存勾选,拖动截图到指定时间段查看发生内存问题时候到页面展示,并定位问题。同时可以查看对应出现红点到执行脚本,定位问题代码。

js删除节点的方法(JSfor循环删除指定节点)

基于 Benchmark.js

慎用全局变量

  • 全局变量定义在全局执行的上下文,是所有作用域链的顶端
  • 全局执行上下文一直存在于上下文执行栈,直到程序退出
  • 如果某个局部作用域出现了同名变量则会屏蔽或者污染全局作用域
  • 全局变量的执行速度,访问速度要低于局部变量,因此对于一些需要经常访问的全局变量可以在局部作用域中进行缓存

js删除节点的方法(JSfor循环删除指定节点)

上图可以看出,test2 的性能要比 test1 的性能要好,从而得知,缓存全局变量后使用可以提升性能

通过原型对象添加附加方法提高性能

js删除节点的方法(JSfor循环删除指定节点)

上图可以看出,test2 的性能要比 test1 的性能要好不少,从而得知,直接访问属性,会比通过方法访问属性速度来的快。

遍历速度

js删除节点的方法(JSfor循环删除指定节点)

上图可以看出,loop 遍历速度 forEach > 优化 for > for of > for > for in

(0)
小多多的头像小多多创始人

相关推荐

发表回复

登录后才能评论