JS性能优化1
Document
2020-09-29
JS性能优化1
内存管理:
- 内存:由可读写的单元组成,表示一片可操作性的空间
- 内存管理:开发者可以主动的申请、使用、释放空间
- 内存的申请:定义一个变量会自动分配一个空间 即:let obj = {}
- 内存的使用:obj.name = 'lanpang'
- 内存的释放:obj = null
垃圾回收:
- 对象不再被引用时,则被视为垃圾
- 对象由于某些原因 例如:代码错误 导致再也不能被从根上访问到,则也视为垃圾
- 可达对象:就是 从根上触发是否能够被找到 可以访问到的对象(引用、作用域链)在JS中 根可以理解为全局变量对象
引用计数算法:
- 每个对象都会有一个对应的引用数值
- 一旦某个对象的引用数值为0 那么就会被当做垃圾回收
- 优点
- 引用计数算法会在发现垃圾的时候立即回收
- 最大限度减少程序暂停
- 缺点:
- 时间消耗大 因为要时刻监控着引用数值是否需要修改
- 无法回收循环引用的对象 如以下代码演示
function fn1() { const obj1 = {} const obj2 = {} obj1.name = obj2; obj2.name = obj1; return '111'; } fn1(); // 当执行完函数调用的时候 在全局中已经找不到obj1和obj2了 obj1和obj2的引用应该为0 // 此时通知GC去删除 但是GC发现obj1有一个属性指向了obj2 同样obj2也有属性指向obj1 // 因为他们在fn1这个作用域中有互相引用所以引用计数器其实不为0 此时引用计数算法的GC没法将obj1 obj2回收 // 类似的这种互相引用的对象 引用计数器算法的GC都无法处理
标记清除算法:
- 核心思想:分标记和清除两个阶段完成
- 1、遍历全局所有可达对象并递归查找可达对象中的子引用关系 将他们标记
- 2、遍历所有对象 把没有标记的对象清除 并把1阶段设置的标记抹掉 方便下次工作
- 优点
- 可以解决循环引用对象的回收
- 缺点:
- 会导致内存空间的碎片化 比如ABC3个变量用了3个空间 清除了AC的空间 但是B在AC的中间隔开了两个内存块
- 这就会导致碎片化 A空间清除后有2个字节的大小 C空间有1个 此时如果刚好要用1.5个字节 那么两者都不合适
- 不能立即回收垃圾对象
标记整理算法:
- 也是两个阶段 第一阶段和标记清除相同
- 清除阶段会先执行整理,移动对象的位置 让目前的可达对象变成连续的
- 可以减少碎片化空间
- 不能立即回收垃圾对象
总结:
- 3种方法各有优缺点