前端学习笔记Part1-2:JS性能优化、GC算法介绍和V8引擎

JavaScript 性能优化

JavaScript 内存管理

  • 内存管理介绍
    • 内存:有可读写单元组成,表示一片可操作的空间
    • 管理:人为的去操作一片空间的申请、使用和释放
    • 内存管理:开发者主动申请空间、使用空间、释放空间
    • 流程管理:申请–使用–释放
  • JavaScript申请内存空间、使用内存空间、释放内存空间
    //申请
    let obj = {}
    //使用
    obj.name = 'lg'
    //释放
    obj = null
    
  • JavaScript 中的垃圾回收
    • JavaScript中的垃圾
      JavaScript中内存的管理是自动的
      对象不再被引用时就是垃圾
      对象不能从根上访问到时是垃圾
    • JavaScript 中的可达对象
      可以访问到的对象就是可达对象(引用、作用域链)
      可达的标准是从根出发是否能够被找到
      JavaScript中的根可以理解为是全局变量的对象
    //引用
    let obj = {name: 'xm'}
    
    let ali = obj
    
    obj = null
    //可达
    function objGroup(obj1, obj2){
        obj1.next = obj2
        obj2.prev = obj1
        return {
            o1: obj1,
            o2: obj2
        }
    }
    let obj = objGroup({name: 'obj1'},{name: 'obj2'})
    
    console.log(obj)
    

GC 算法介绍

  • GC算法定义
    • 定义:GC就是垃圾回收机制
    • 作用:可以找到内存中的垃圾、并释放和回收空间
      GC的垃圾是什么:1、程序不再需要使用对象,2、程序找不到的对象
    • 算法就是工作时查找和回收立即所遵循的规则
  • 常见的GC算法
    • 引用计数算法
      工作原理:引用计数的含义是跟踪记录每个值被引用的次数。当声明了一个变量并将一个引用类型值赋给该变量时,则这个值的引用次数就是 1。如果同一个值又被赋给另一个变量,则该值的引用次数加 1。相反,如果包含对这个值引用的变量又取得了另外一个值,则这个值的引用次数减 1。当这个值的引用次数变成 0 时,则说明没有办法再访问这个值了,因而就可以将其占用的内存空间回收回来。
      核心思想:设置引用数,判断当前引用数是否为0
      引用计数器:
      引用关系改变时修改引用数字,引用数字为0时立即回收
    //引用计数
    const user1 = {age: 11}
    const user2 = {age: 22}
    const user3 = {age: 33}
    
    const nameList = [user1.age, user2.age, user3.age ]
    
    function fn() {
        const num1 = 1
        const num2 = 2
    }
    fn() //函数执行完后num1/num2就会回收    
    
    • 引用计数算法的优缺点
      优点:1、发现垃圾时立即回收,2、最大限度减少程序暂停
      缺点:1、无法回收循环引用的对象,2、资源消耗大
    //对象的循环引用
    function fn() {
        const obj1 = {}
        const obj2 = {}
        pbj1.name = obj2
        obj2.name = obj1
        return 'lg is a code'
    } 
    fn() //obj1和obj2循环引用,导致引用计数算法无法回收这两个对象
    
    • 标记清除算法
      核心思想:分标记和清除两个阶段完成,第一阶段:遍历所有对象并标记可达对象,第二阶段:遍历所有对象清除没有标记的对象并清除第一阶段的标记,最后回收相应的空间
      优点:解决对象循环引用无法回收的问题
      缺点:空闲链表地址不连续,导致空间碎片化,空间无法达到最大化的使用
    • 标记整理算法
      标记整理算法就是标记清楚的增强:在第一阶段的标记工作完全一样,将当前可达对象标记,第二阶段不用,在第二阶段的清除之前会先做一个整理工作,移动活动对象的位置使之在位置上产生连续

V8引擎

  • 认识V8:1、目前市面上最主流的JavaScript执行引擎;2、采用即时编译,速度快;3、内存有上限(64位1.5G,32位800M);4、V8将内存空间一分为二(新生代和老生代),新生代大小为(32M|16M,对应64位和32位),新生代指存活时间较短的对象(局部变量),老生代大小为(1.4G|700M,对应64位和32位)
  • V8垃圾回收策略
    • 因为内存是有上限的,所以采用分代回收的思想,内存分为新生代和老生代,针对不同代的对象采用不同算法
    • V8常用的GC算法:分代回收、空间复制、标记清除、标记整理、标记增量
    • V8新生代的垃圾回收
      算法:复制算法和标记整理算法
      垃圾回收过程:新生代内存分为两个等大的区域,使用空间为from,空闲空间为to,活动对象存储于from空间,标记整理后将活动对象拷贝至to空间,from与to空间交换完成后释放from空间。
      回收细节说明:拷贝过程可能出现晋升(新生代对象移动至老生代,一轮GC还存活的新生代对象需要晋升或者to空间的使用率超过了25%)
    • V8老生代的垃圾回收
      老生代对象:存放在老生代区,老生代对象就是指存活时间较长的对象,
      算法:标记清除+标记整理+增量标记
      垃圾回收过程:首先使用标记清除算法完成垃圾空间回收,随后采用标记整理算法进行空间优化,最后采用增量标记进行效率优化
      细节对比:新生代垃圾回收用空间换时间,老年代不适合
      标记增量如何优化垃圾回收:将垃圾回收分成几小步,让垃圾回收和程序执行交替执行。
  • V8垃圾回收总结
    • V8是当前主流的JavaScript执行引擎
    • V8内部内存设置上限
    • V8采用基于分代回收思想实现垃圾回收
    • V8 内存分为新生代和老生代
    • V8 垃圾回收常见的GC算法

Performance工具

  • 基本介绍
    • 为什么使用这个工具:GC的目的是为了实现内存空间的良性循环,良性循环的基石是合理使用,所以必须时刻关注才能确定是否合理,通过Performance就可以实现这种监控。
  • 内存问题的体现
    • 页面出现延迟加载或经常性暂停
    • 页面出现持续性糟糕性能的表现
    • 页面的性能随时间的延长越来越差
  • 监控内存的几种方式
    • 三种内存问题的界定
      内存泄漏:内存使用的持续升高
      内存膨胀:在多数设备上都存在的性能问题,才是内存膨胀
      频繁垃圾回收:通过内存变化图分析

    • 监控内存的方式
      浏览器任务管理器
      Timeline 时序图记录
      堆快照查找分离DOM
      判断是否存在频繁地垃圾回收

    • 任务管理器监控内存
      shift+esc调用浏览器的任务管理器

    • Timeline 记录内存变化

    • 堆快照功能查找分离DOM
      工作原理:找到当前的JS堆,进行一个照片的留存,找到分离DOM并删除
      垃圾DOM:从DOM树上脱离且没有被引用
      分离DOM:从DOM树上脱离但是在JS代码中仍然被引用

    • 判断是否存在频繁地垃圾回收
      垃圾回收的缺点:GC工作时应用程序是停止的,频繁且过长的GC会导致应用假死,用户使用中会感知应用卡顿。
      两种方式:1、Timeline中频繁上升下降,2、任务管理器中数据频繁地增加减少

  • Performance总结
    1、Chrome提供的工具,通过使用该工具可以监控程序对内存的使用,以发现内存使用的问题并优化程序

代码优化

你可能感兴趣的:(前端学习笔记Part1-2:JS性能优化、GC算法介绍和V8引擎)