JavaScript 语言性能优化

2020-06-27  本文已影响0人  望月从良glh

说明: 具体从内存空间的使用以及垃圾回收机制的角度出发。

内存管理

申请空间-使用空间-释放空间

// 申请空间
let obj = { name: 'glh' };
// 使用空间
let ali = obj;
// 释放空间
obj = null;

JavaScript中的垃圾

可达对象

GC 算法

所谓的GC算法就是垃圾回收器工作的时候查找和回收所遵循的规则

常见的GC算法

引用计数

在内部维护一个引用计数器,给每个对象设置引用数,当引用关系发生变化时,判断当前对象引用数是否为 0,当为 0 时候,当前对象为垃圾对象,被 GC 回收且释放内存空间

function(){
  const obj1 = {}
  const obj2 = {}
  obj1.name =  obj2
  obj2.name = obj1  
   return ''
}
f()

以上代码在采用引用计数算法进行垃圾回收时,并不会对obj1和obj2进行回收,因为互相存在引用

如果一个对象的引用数为 0,则该对象将被回收。程序运行时,对内存的消耗除逻辑代码外,也包括了 GC 算法的消耗,引用计数固然可以在程序出现垃圾的时候可以及时回收释放内存,也因内存可以不断得到释放而减少了程序暂停的时间,但是 GC 同时也需要维护‘roots’表来统计引用计数,当代码中引用较多时,也会带来损耗。同时对于 对象之间互有引用的情况,即使对象本身没有被使用,但是引用存在就导致了引用计数不为 0,无法被回收的情况。

标记清除算法

标记清除算法会递归的寻找对象之间的引用获取所有可达对象,并为其做上标记, 但是标记清除算法所回收的内存地址在内存上不一定是连续的,这就导致了内存空间的碎片化(类似磁盘碎片), 浪费空间,并且标记清除法是不会立即回收对象的,而且当标记清除算法运行的时候,程序会被暂停

优点:循环引用的对象也会被回收 缺点:不会立即回收垃圾对象

标记整理算法

标记整理算法增强了标记清除算法,遍历所有内存对象,将所有可达内存对象标记,其在回收非活动对象前会将对象的地址进行移动,使其在地址上连续,然后再回收。

优点:不会存在内存空间的碎片化 缺点:不会立即回收垃圾对象

V8 简介

由于 V8 的运行内存是有上限的,因此垃圾回收需要使用分代回收算法,然后针对于新/老生代对象采取不同的 GC 算法

V8中常用的GC算法
V8的垃圾回收策略
新生代对象的回收操作

细节说明:

老生代对象的回收操作
新老生代垃圾回收细节对比
内存问题的外在表现
使用任务管理器查看内存

唤起浏览器自带的任务管理器,观察 js 内存,如果 js 内存在持续增大,则存在内存问题。

Timeline 记录内存

打开 Timeline 开始录制,进行页面操作,结束录制之后,开启内存勾选,拖动截图到指定时间段查看发生内存问题时候到页面展示,并定位问题。同时可以查看对应出现红点到执行脚本,定位问题代码。

利用浏览器控制台内存模块,查找分离 dom

在页面上进行相关操作后,进行“拍照”,在快照中查找Detached HTMLElement,回到代码中查找对应的分离 dom 存在的代码,在相关操作代码之后,对分离 dom 进行释放,防止内存泄漏。

如何确定频繁的垃圾回收操作

代码优化

慎用全局变量
一些性能上的小问题
上一篇 下一篇

猜你喜欢

热点阅读