垃圾回收

  1. js中内存管理是自动的
  2. 对象不再被引用时是垃圾
  3. 对象不能从根上访问到时是垃圾可达对象:1.可以访问到的对象就是可达对象 2.可达标准是从根出发是否能被找到 3.js中的根可以理解为全局变量对象

    GC算法

  4. 引用计数算法

  • 核心思想:设置引用数,判断当前引用数是否为0
  • 引用计数器
  • 引用关系改变时修改引用数字
  • 引用数字为0时立即回收
  1. 引用计数算法优缺点
  • 发现垃圾时立即回收
  • 最大限度减少程序暂停
  • 无法回收循环引用的对象
  • 时间开销大
  1. 标记清除算法
  • 核心思想:分标记和清除两个阶段完成
  • 遍历所有对象找标记活动对象(递归查找)
  • 遍历所有对象清除没有标记的对象,同时把第一次遍历所做的标记抹掉
  • 把回收的空间放到空闲列表上面,方便后续程序申请空间使用
  1. 标记清除算法优缺点
  • 可以解决循环引用的对象
  • 地址不连续,空间碎片化
  1. 标记整理算法
  • 是标记清除的增强
  • 标记阶段的操作和标记清除一致
  • 清除阶段会先执行整理,移动对象位置
  1. V8引擎
  • 即时编译
  • V8内存设限 64位 1.5G 32位 800M
  1. V8垃圾回收策略
  • 采用分代回收的思想
  • 内存分为新生代、老生代
  • 针对不同对象采用不同算法
    1. 1. 分代回收
    2. 1. 空间复制
    3. 1. 标记清除
    4. 1. 标记整理
    5. 1. 标记增量
  1. V8内存分配
  • V8内存空间一分为二
  • 小空间用于存储新生代对象(64位:32M | 32位:16M)
  • 新生代指的是存活时间较短的对象(局部作用域中的变量)
  1. 新生代对象回收实现
  • 回收过程采用复制算法 + 整理标记
  • 新生代内存区分为两个等大小空间
  • 使用空间为From,空闲空间为To
  • 所有对象存储于From空间(包括活动对象和非活动对象)
  • 当From空间应用到一定程度后会触发GC机制,标记整理后将活动对象拷贝至To
  • From完成释放(From和To交换空间)回收细节说明:
    1. 拷贝过程中可能出现晋升
    2. 晋升就是讲新生代对象移动至老生代
    3. 一轮GC还存活的新生代需要晋升
    4. To空间的使用率超过25%需要晋升至老生代
  1. 老生代对象回收
  • 老生代对象存放在右侧老生代区域
  • 64位限制1.4G,32位限制700M
  • 老生代对象就是指存活时间较长的对象(全局变量,闭包)
    实现过程:
    1. 主要采用标记清除、标记整理、增量标记算法
    2. 首先使用标记清除完成垃圾空间的回收
    3. 采用标记整理进行空间优化(当新生代晋升老生代时,同时也发现老生代空间不够存新生代晋升过来的,就会进行标记整理空间优化)
    4. 采用增量标记进行效率优化(将标记过程分段进行)
  1. 内存问题的外在表现
  • 页面出现延迟加载或经常性暂停
  • 页面持续性出现糟糕的性能(内存膨胀,分配的内存超过机器能力)
  • 页面的性能随时间延长越来越差(内存泄漏)
  1. 监控内存的几种方法
    界定内存问题的标准
  • 内存泄漏:内存使用持续升高
  • 内存膨胀:在多数设备上都存在性能问题
  • 频繁垃圾回收:通过内存变化图进行分析监控方式:
    1. 浏览器任务管理器
    2. TImeline时序图记录
    3. 堆块照查找分离DOM(分离DOM存在是一种内存泄漏)
    4. 判断是否存在频繁的垃圾回收
  1. 什么是分离DOM
  • 界面元素存活在DOM树上
  • 垃圾对象时的DOM节点
  • 分离状态的DOM节点

    代码优化

  1. 慎用全局变量
  • 所有作用域链的顶端,所以会比较耗时,尽量放在局部作用域
  • 不利于GC机制,耗内存
  • 全局变量命名污染
  1. 缓存全局变量
  2. 通过原型新增方法来替代构造函数中新增方法
  3. 避开闭包陷阱(容易内存泄漏)
  4. 避免属性访问方法使用
  5. for循环优化。将长度缓存
  6. 采用最优循环方式:简单遍历的话 foreach 优于 for 优于 for in
  7. 节点添加优化(回流和重绘):createDocumentFragment() 文档碎片方法优于直接添加到body
  8. 克隆优化节点操作:cloneNode(false)
  9. 直接量替换Object操作```
    var a = [1, 2, 3] // 性能好
    var a1 = new Array(3)
    a1[0] = 1
    a1[1] = 2
    a1[2] = 3