Js性能优化之内存问题的表现和监控

1,616 阅读3分钟

「这是我参与11月更文挑战的第12天,活动详情查看:2021最后一次更文挑战

内存问题的外在表现

  • 页面出现延迟加载或经常性暂停(网络环境正常的)

    任务:如何使用Performance进行观察?

  • 页面持续性出现糟糕的性能

    内存膨胀:页面为了使用的流畅,去申请一段非常大的内存空间,空间超出当前的负载

  • 页面性能随时间延长越来越差 内存溢出的情况,刚刚开始内存泄漏还没有出现堆叠的情况,内存就保留有较多的空间,用户就不会体验到明显的卡顿,在内存泄漏堆叠情况严重造成内存溢出之后,就会出现明显的卡顿

监控内存

我们常见的内存出现问题有三种情况:

  • 内存泄漏
  • 内存膨胀
  • 频繁的垃圾回收

界定内存问题的标准

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

监控内存的几种方式

  • 浏览器任务管理器
  • Timeline 时序图记录
  • 堆快照查找分离DOM
  • 判断是否存在频繁的垃圾回收

浏览器任务管理器

我们就先创建一个html文件进行浏览器的性能试验

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>任务管理器监控内存变化</title>
  </head>
  <body>
    <button id="btn">ADD</button>
    <script type="text/javascript">
      const btn = document.getElementById("btn");
      btn.onclick = function() {
        let arr = new Array(100000);
      }
    </script>
  </body>
</html>

然后打开该html文件,通过快捷键Shift+Esc按钮调出浏览器任务管理器

image.png 选中任意一个右键-> 选中 JavaScript使用的内存 image.png 那我们如何查看内存使用呢?

首先我们会发现有两个内存:

  • 内存占用空间 -> DOM节点占用的内存,如果内存不断加大,就是不断在新增DOM节点
  • JavaScript使用的内存: 所有可达对象的使用内存,如果值在不断加大,就是说明我们当前在不断新增对象,或者是可达对象的值不断在增长 ok明白这些之后我们开始测试: image.png 点击add按钮

image.png 我们会发现使用内存明显增加了许多,确实是有监听到内存的使用的。

Timeline 时序图记录

老规矩上测试用例

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>任务管理器监控内存变化</title>
  </head>
  <body>
    <button id="btn">ADD</button>
    <script type="text/javascript">
      const arrList = []
      function test() {
        for(let i = 0; i< 100000; i++){
          document.body.appendChild(document.createElement('p'))
        }
        arrList.push(new Array(100000).join('x'))
      }
      const btn = document.getElementById("btn");
      btn.addEventListener('click', test)
    </script>
  </body>
</html>

打卡页面后进入控制台-性能面板 image.png 在我们录制完毕之后,我们点开Memory内存面板

image.png 面板按顺序是:

  • js堆
  • 文档
  • 节点
  • 监听器
  • GPU 现在按照我们的图进行一下评比: 首先很长一段时间,我们的浏览器的执行都是平稳状态,如何多次起伏就是我们的事件触发+垃圾回收的情况

image.png

堆快照查找分离DOM

老规矩先上测试用例

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>任务管理器监控内存变化</title>
  </head>
  <body>
    <button id="btn">ADD</button>
    <script type="text/javascript">
      var tempEle
      function test() {
        var ul = document.createElement('ul')
        for(var i = 0; i < 10; i++) {
          var li = document.createElement('li')
          ul.appendChild(li)
        }
        tempEle = ul
      }
      const btn = document.getElementById("btn");
      btn.addEventListener('click', test)
    </script>
  </body>
</html>

image.png

判断是否存在频繁的垃圾回收

  • TimeLine 中频繁的上升下降
  • 任务管理器中数据频繁的增加减小