博客 / 詳情

返回

js性能優化相關內容筆記整理

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變量等
減少判斷層級
  • 儘可能的減少判斷的層級,如果有嵌套判斷,看看是否可以將判斷條件往外提
減少循環體活動
user avatar
0 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.