Javascript性能优化

内存管理(memory management)

概念

  • 内存: 有可读写单元组成,表示一片可操作的空间
  • 管理:人为操作去申请、使用和释放空间
  • 内存管理:就是开发者申请、使用和释放内存空间
  • 管理流程:申请-使用-释放
  • Javascript中的内存管理: 1. 申请空间; 2. 使用空间; 3. 释放空间
//申请
let obj = {};
//使用
obj.name = "test";
//释放
obj = null;

Javascript中的垃圾回收

  • javascript中的内存管理是自动的
  • 什么被看作垃圾: 1.对象不再被引用,2.对象不能从根上被访问到
  • 可达对象不会被看作垃圾: 1.递归可以访问到的对象就是可达对象, 2. 可达标准:从根出发可以被找到, 3. Javascript中的根可以理解为全局对象

GC算法

概念

  • GC就是垃圾回收机制的简写
  • GC可以找到内存中的垃圾,释放并回收空间
  • 算法就是垃圾回收过程中所遵循的规则

常见GC算法

引用计数法

  • 核心:

设置引用数,当引用关系改变时修改引用数,判断引用数,为0时释放回收内存空间

const user1 = {age:11}
const user2 = {age:22}
const user3 = {age:33}

const nameList = [user1.age,user2.age,user3.age]
// user1 user2 user3 仍然被引用 所以不会被回收


function fn(){
  const num1 = 1;
  const num2 = 2;
}

fn(); //在执行后 内部num1 num2 就会被回收
  • 优点:
  1. 发现垃圾时立即回收
  2. 最大限度减少程序暂停
  • 缺点:
  1. 无法回收循环引用的对象
  2. 时间开销大

标记清除算法

  • 核心

分为标记和清除两个阶段

标记阶段: 遍历所有对象,标记活动对象,再次遍历,找到没有标记的对象,并且清除第一次的标记

清楚阶段: 回收没有标记对象所占空间

  • 优点

可以回收循环引用对象

  • 缺点

空间碎片化(内存空间释放后地址不连续)

不能立即回收垃圾

标记整理算法

  • 核心

可以看作时标记清楚算法的增强

标记阶段: 和标记清楚算法的标记阶段相同

清楚阶段:先执行整理,移动对象位置使其紧邻

  • 优点

解决空间碎片化

  • 缺点

不能立即回收垃圾

 

 V8

概念

  • V8是Javascript中的一种执行引擎,在Node中也使用
  • V8采用即时编译
  • 内存空间设限(64位-1.5G, 32位-800M)

回收策略

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

 常用的GC算法

分代回收

空间复制

标记清楚

标记整理

标记增量

处理新生代对象

  • 新生代对象: 存活时间较短的对象(局部变量)
  • 处理前V8将空间一分为二,小空间(64位32M,32位16M)来存放新生代对象
  • 回收过程

1. 回收采用空间复制和标记整理法

2. 先将新生代内存区等分为二(from/to)

3. from称为使用空间,to称为空闲空间

4. 活动对象放入from空间

5. 标记整理后将from空间中的活动对象拷贝到to

6. 然后to和from交换完成释放

  •  需要注意
  1. 拷贝过程中可能出现晋升(晋升就是将新生代对象移动至老生代)
  2. 晋升条件: 一轮GC还存活的新生代需要晋升; To 空间的使用率超过25%

 

处理老生代对象 

  • 老年代对象:存活时间较长的对象
  • 存放位置:在右侧老年代区域
  • 大小限制: 64位操作系统1.4G, 32位操作系统700M
  • 回收过程
  1. 主要采用标记清除,标记整理,增量标记算法
  2. 首先用标记清除完成垃圾空间的回收
  3. 采用标记整理进行空间优化
  4. 采用增量标记进行效率优化(因为垃圾回收会阻碍程序执行,此处程序执行和垃圾回收交替执行,既不会暂停很久,也可以回收垃圾,用户体验感好)
  • 新生代区域和老年代区域细节对比
  1. 新生代区域垃圾回收使用空间换时间
  2. 老生代区域垃圾回收不适合复制算法

 

总结

  1. V8 是一款主流的JavaScript执行引擎
  2. V8 内存设置上限
  3. V8 采用基于分代回收思想实现垃圾回收
  4. V8 内存分为新生代和老生代
  5. V8 垃圾回收常见 GC 算法

 

Performance 工具

作用:

时刻监控内存的使用情况

何时使用

1.页面出现延迟加载或者经常性暂停

2.持续性糟糕体验

3.随着时间过长页面性能越来越差

监控内存的几种方式

1.浏览器任务管理器

2.timeline时序图记录

3.堆快照查找分离DOM

4.判断是否出现频繁垃圾回收

打开performance工具

1. 打开浏览器,输入地址

2. 打开开发者工具,选择性能

3.使用对应工具,用户操作,然后记录内存变化

下面是chrome的工具截图 

 

下面是firefox的工具截图

一些概念

什么是分离Dom: 在界面上看不到,但是在JS代码中仍然引用,这种分离Dom会占用内存,GC无法回收,因此可以利用堆快照查找这些分离Dom

为什么要判断是否频繁GC: GC会导致程序暂停,频繁GC程序就会卡死,用户就会体验到卡顿

如何判断是否频繁GC: timeline内存频繁上升下降,浏览器任务管理器频繁增加减小

 

JS代码优化

可以将代码粘贴至网址去对比测试:https://jsperf.com/(本机访问失败)

优化点 

  • 慎用全局变量

全局变量存在于全局执行上下文,是所有作用域的顶端

全局变量一直存在于上下文执行栈中,直到程序结束

局部作用域中若存在和全局变量同名的情况,会污染全局变量

  • 缓存全局变量

将无法避免使用的全局变量放入局部作用域中

  • 通过原型对象添加方法,性能更优

  • 避免闭包陷阱

  • 避免属性访问方法的使用,性能更优

  • for循环优化(将length的数值变为一个固定的值,如:var k= arr.length ;  i < k; 性能更好)
  • forEach, for, for-in循环比较

简单逻辑用ForEach, 然后可以用for, 最后考虑for-in

  • 文档碎片优化节点添加

  • 克隆优化节点

  • 直接量替换New Object,性能更优

  • 减少判断层级

  • 减少作用域链查找层级

  • 减少数据读取次数

  • 字面量和构造式

  • 减少循环体中的活动

  • 减少声明和语句数

  • 采用事件绑定 

JSBench

比对两段代码性能的工具网站,网址:https://jsbench.me/

堆栈中的JS执行过程

JS代码的执行会在堆中放一个执行环境栈

先创建一个全局上下文,进行全局作用域的变量的存放: 基础类型放入栈中,引用类型放入堆中,函数的声明放入栈中,地址指向堆

函数的调用会单独开启一个上下文,执行完毕根据是否有闭包决定是否释放当前内存

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值