js性能优化学习笔记2-Performance工具

460 阅读3分钟

Performance 工具

为什么要使用

GC的目的是为了实现内存空间的良性循环,js中并没有提供操作内存的api,所以当我们写代码的时候无法判断是否合理使用了内存空间,performance 就提供了时刻监控内存的方式。

内存问题

  • 页面出现延迟加载或经常性暂停,可能存在频繁的GC操作,可以通过内存变化图进行分析
  • 页面持续性出现糟糕的性能,可能出现了内存膨胀,指当前界面为了达到最佳的使用速度而去申请了一定的内存空间,但是这个内存空间远超过了当前设备本身(和设备的硬件相关)能提供的大小
  • 页面的性能随时间延长越来越差,可能出现了内存泄露,内存使用持续升高,使内存空间越来越少

1. 浏览器任务管理器

  1. 模拟一个 html 页面,代码如下
<body>
  <button id="btn">Add</button>
  <script>
    const oBtn = document.getElementById('btn')
    oBtn.onclick = function() {
        let arrList = new Array(1000000)
    }
  </script>
</body>
  1. 在浏览器中打开这个 html 页面,通过 shift + esc 快捷键调出浏览器任务管理器,可以看到下面的图片(如果没有 js 内存项,可以右键进行选择) image.png
    • 内存占用空间:DOM 节点所占据的内存,如果这个内存一直增大,则表示界面正在不断创建新 DOM
    • javaScript使用的内存: 表示 js 中的堆内存,小括号里的值表示的是所有可达对象正在使用的内存大小,如果这个数值一直增大,则表示当前界面中正在创建新对象或现有对象在不断增长
      可以看到打开界面之后javaScript内存中的值一直不变,就是没有对象在增长的
  2. 触发 Add 按钮,可以看到 js 内存明显变大 image.png 通过观察这个内存的变化,我们可以看出代码是否存在问题,但具体问题难以定位。

2. Timeline 时序图记录

  1. 模拟一个 html 页面,代码如下
  <button id="btn">Add</button>
  <script>
    const arrList = []
    function test() {
        for(let i = 0;i< 100000; i++){
            document.body.appendChild(document.createElement('p'))
        }
        arrList.push(new Array(1000000).join('x'))
    }
    document.getElementById('btn').addEventListener('click', test)
  </script>
  1. 调出控制台,找到perfprmance面板,开始记录
  2. 触发3次 Add 按钮,然后停止记录,根据图示查看js内存的变化 image.png 根据这个图表可以分析:
  • 一开始点击 Add 按钮前处于平稳的状态,没有太多的内存消耗
  • 第一次点击 Add 之后,内存瞬间暴涨,然后保持处于一个高峰状态
  • 当脚本运行稳定之后,GC 可能在某个时间点开始工作,发现一些非活动对象并进行回收,所以高峰之后会有一个下降的过程
  • 在下降的区间中会有一些小的波动,属于正常的开销,后面的点击也会造成同样的暴涨和下降。
  • 这样有升有降是正常的内存变化,升就是申请内存,降就是GC回收,如果一直保持上涨,就表示内存有不正常的消耗了,有可能是内存泄漏。
  • 当发现问题的时候,可以拖动上方的时序图,找到出问题的毫秒页面的样子,从而定位问题

3. 堆快照查找分离 DOM

分离DOM:脱离DOM树,但是在js中还在被引用的DOM节点。这种DOM在页面上看不见,但是在内存中还占据着空间,这就是一种内存泄漏。

  1. 模拟一个 html 页面,代码如下
  <button id="btn">Add</button>
  <script>
    var tmpEle
    function test() {
      var ul = document.createElement('ul')
      for(let i = 0;i< 10; i++){
        var li = document.createElement('li')
        ul.appendChild(li)
      }
      tmpEle = ul
      // tmpEle= null 直接置空既可以解决分离DOM的问题
    }
    document.getElementById('btn').addEventListener('click', test)
  </script>
  1. 调出控制台,找到memory面板,拍摄堆快照(Heap snapshot -> take snapshot)
  2. 拍摄的照片中就是当前活动对象的展示,可以搜索detached(分离DOM),发现没有相关的内容
  3. 触发 Add 按钮,再次拍摄堆快照,同样搜索detached,可以发现搜索结果中有了内容,就是我们在 js 中添加的 DOM节点(分离DOM) image.png

判断是否存在频繁的 GC 操作

  1. timline中频繁的上升下降
  2. 任务管理器中数据频繁的增加减小

学习自拉钩教育前端视频