5

GC 算法

1. 引用计数

核心思想:设置引用数,判断当前引用是否为0

优点:

  1. 发现垃圾时,立即回收
  2. 最大限度减少程序暂停

缺点:

  1. 无法回收循环引用的对象
  2. 时间开销大(需要监听计数值的变化)
function fn() {
    const obj1 = {}
    const obj2 = {}
}

2. 标记清除

核心思想:分标记和清除两个阶段

缺点:
1、 空间碎片化(回收对象在地址上的不连续)
2、 不能立即回收

3. 标记整理

标记,然后将活动对象的地址进行整理,尽量使得活动对象地址连续

4. 分代回收

回收新生代对象(存活时间较短的变量对象)
  • 回收过程采用复制算法+标记整理
  • 新生代内存区分为两个等大小的空间
  • 使用空间为From,用于存储活动对象, 空闲空间为To,用于存储From中的活动对象
  • 活动对象存储于From空间
  • 标记整理后将活动对象拷贝至To
  • From 与To交换空间完成释放

回收细节:From和To之间的拷贝过程可能出现晋升(将新生代对象移动至老生代)下面两种情况会产生晋升

  • 一轮GC后还存活的新生代需要晋升
  • To空间的使用率超过了25%
回收老生代对象

空间大,无法使用复制算法,使用增量标记法优化效率

  • 标记清除
  • 标记整理: 使得活动对象的地址连续
  • 标记增量: 将原本标记整理的工作拆分为多个小的标记工作,防止程序阻塞

V8

v8垃圾回收策略

v8内存有上限

  1. 采用分代回收思想
  2. 内存分为新生代,老生代
  3. 针对不同对象,采用不同算法

常用算法

  • 分代回收
  • 空间复制
  • 标记清除
  • 标记整理
  • 标记增量

频繁GC(垃圾回收)会带来什么

  • GC工作时,应用程序是停止的
  • 频繁且过长的GC会导致应用假死
  • 用户使用中感知应用卡顿

如何确定是否频繁回收垃圾:

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

堆快照查找分离dom,这个都是无用的dom引用,需要使用堆快照功能超找
detachedNode
image.png

v8引擎执行流程

image.png

代码优化 函数嵌套会导致v8进行多次的预解析,因此不要嵌套太深

堆栈操作

  • js执行环境
  • 执行环境栈(ECStack, execution context stack)
  • 执行上下文
  • VO(G),全局变量对象
  • EC(G),全局执行上下文

基本类型 (栈操作)

  • 基本数据类型是按值进行操作
  • 基本数据类型值是存放在区的
  • 无论我们当前看到的栈内存,还是后续引用数据类型会使用的堆内存都属于计算机内存
  • GO(全局对象)

引用类型 (堆操作)

  1. 函数执行

    1. 确定作用域链(当前执行上下文,上级执行上下文)
    2. 确定this指向,如果是在全局作用域那么就是window
    3. 初始化arguments对象
    4. 形参赋值
    5. 变量提升(var声明的关键字,或者函数内部的function声明)
    6. 执行代码
    7. 如果函数内部没有被其他地方所引用,那么就会进行出栈操作,释放栈内存
  2. 闭包理解

    function fn() {
     var a = 1
     return function(b) {
         console.log(a + b)
     }
    }
    const f = fn()
    f(5)
    f10()
    1. 闭包是一种机制,通过私有的上下文来保护其中的变量的一种机制
    2. 也可以认为,在创建的某一个执行上下文不被释放的时候 就形成了闭包
    3. 保护、保存数据

循环添加事件,看闭包使用的取舍

如果使用闭包,进行多个事件的注册,因为闭包的原因,会申请一个对地址来保存,如果事件越多,那么申请的内存越多,因此需要用到事件代理

变量的申明

变量申明最好是放在局部变量,否则代码在执行的时候 查找作用域链上的变量会比较花时间, 对比下面两段代码 使用的是 jsbench这个工具

var i, str = ""

function parseDom() {
   for(i = 0; i < 100; i++) {
       str += i
   }
}
parseDom()

function parseDom() {
   let str = ''
   for(let i = 0; i < 100; i++) {
       str += i
   }
}
parseDom()

image.png

变量缓存
  • 数组长度
  • 多次使用的dom变量等
减少判断层级
  • 尽可能的减少判断的层级,如果有嵌套判断,看看是否可以将判断条件往外提
减少循环体活动

路飞的笑
119 声望3 粉丝

人活着就要做有意义的事情。