JavaScript性能優(yōu)化

性能優(yōu)化主要相關(guān)模塊

  1. 內(nèi)存管理
  2. 垃圾回收與常見GC算法
  3. V8引擎的垃圾回收
  4. Performance工具
  5. 代碼優(yōu)化實例

1. 內(nèi)存管理

JavaScript 內(nèi)存管理 Memory Management

? 內(nèi)存為什么需要管理
function fn() {
    arrList = []
    arrList[100000] = 'lg is a coder'
}
fn()

內(nèi)存管理介紹

  • 內(nèi)存: 由可讀寫單元組成徙瓶,表示一片可操作空間
  • 管理:人為的去操作一片空間的申請、使用和釋放
  • 內(nèi)存管理:開發(fā)者主動申請空間集侯、使用空間新症、釋放空間
  • 管理流程: 申請-使用-釋放

JavaScript 中的內(nèi)存管理

  • 申請內(nèi)存空間
  • 使用內(nèi)存空間
  • 釋放內(nèi)存空間
// 申請
let obj = {}
// 使用
obj.name = 'lg'
// 釋放
obj = null

2. 垃圾回收與常見GC算法

2.1 垃圾回收

JavaScript 中的垃圾

  • JavaScript中的內(nèi)存管理是自動的
  • 對象不再被引用時是垃圾
  • 對象不能從根上訪問到時 是垃圾

JavaScript 中的可達對象

  • 可以訪問到的對象就是可達對象 (引用、作用域鏈)
  • 可達的標(biāo)準就是從根出發(fā)是否能夠被找到
  • JavaScript 中的根就可以理解為是全局變量對象

JavaScript 中的引用和可達

let obj = {name: 'xm'} // 聲明了一個xm的內(nèi)存空間

let ali = obj // ali也引用了這個空間

obj = null // obj斷開與xm的內(nèi)存空間連接媚创,但是ali還引用著

2.2 GC 算法介紹

  1. GC 就是垃圾回收機制的簡寫
  2. GC 可以找到內(nèi)存中的垃圾昧互、并釋放和回收空間

GC中的垃圾是什么

  • 程序中不再需要使用的對象
function func() {
    name = 'lg'
    return `${name} is a coder`
}
func()
  • 程序中不能再訪問到的對象
function func() {
    const name = 'lg'
    return `${name} is a coder`
}
func()

GC 算法是什么

  1. GC 是一種機制筋蓖,垃圾回收器完成具體的工作
  2. 工作的內(nèi)容就是查找垃圾釋放空間荤西、回收空間
  3. 算法就是工作時查找和回收所遵循的規(guī)則

常見GC算法

  • 引用計數(shù)
  • 標(biāo)記清除
  • 標(biāo)記整理
  • 分代回收

2.3 引用計數(shù)澜搅、標(biāo)記清除、標(biāo)記整理

1. 引用計數(shù)

引用計數(shù)算法實現(xiàn)原理

  • 核心思想: 設(shè)置引入數(shù)邪锌,判斷當(dāng)前引用數(shù)是否為0
  • 引用計數(shù)器
  • 引用關(guān)系改變時修改引用數(shù)字
  • 引用數(shù)字為0時立即回收

引用計數(shù)算法優(yōu)點

  • 發(fā)現(xiàn)垃圾時立即回收
  • 最大限度減少程序暫停

引用計數(shù)算法缺點

  • 無法回收循環(huán)引用的對象
  • 時間開銷大

2.標(biāo)記清除

標(biāo)記清除算法實現(xiàn)原理

  • 核心思想:分標(biāo)記和清除二個階段完成
  • 遍歷所有對象找標(biāo)記活動對象
  • 遍歷所有對象清除沒有標(biāo)記對象

(注意:在第二階段當(dāng)中勉躺,會把第一個階段所設(shè)置的標(biāo)記給抹掉,便于我們GC下次能正常工作)

  • 回收相應(yīng)的空間

標(biāo)記清除算法圖示

會把回收的空間直接放在一個叫做空閑列表上面觅丰,方便我們后續(xù)的程序可以直接在這兒可以申請使用

標(biāo)記清除算法優(yōu)點

*. 標(biāo)記清除可以解決循環(huán)引用問題

標(biāo)記清除算法缺點

  • 空間的碎片化

由于當(dāng)前所回收的垃圾對象在地址上它本身是不連續(xù)的饵溅,從而造成我們回收之后它們分散在各個角落,后續(xù)如果我們需要使用妇萄,剛好巧了概说,新的生成空間剛好與之匹配那可以直接用,一但多了或是少了就不太適合使用了嚣伐。

// 任何的空間都會有兩個部分
// 1. 頭(存儲這個空間的元信息 eg: 大小,地址 --- 稱為頭)
// 2. 域 (存放數(shù)據(jù)的)

// 如下圖  假設(shè)一個方塊是1個內(nèi)存空間  左邊藍色的釋放后得2個空間萍丐、右邊藍色的釋放后得1個空間轩端,在釋放完成后,其實它們是分散的逝变,也就是地址不連續(xù)基茵。
// 地址不連續(xù)
// 如果下一次需要申請1.5的空間,左邊多了壳影,右邊少了拱层。 最大問題-空間碎片化



缺點圖示

總結(jié):相對引用計數(shù)來說,解決了循環(huán)引用問題宴咧,缺點則是造成空間碎片化根灯,不能讓空間得到最大化的使用


3. 標(biāo)記整理

標(biāo)記整理算法實現(xiàn)原理

  • 標(biāo)記整理可以看做是標(biāo)記清除的增強
  • 標(biāo)記階段的操作和標(biāo)記清除一致
  • 清除階段會先執(zhí)行整理,移動對象位置 -- 保證地址連續(xù)性

標(biāo)記整理算法圖示

2.2 GC算法總結(jié)

引用計數(shù)優(yōu)缺點
  • 優(yōu)點:
    • 可以即時回收垃圾對象
    • 減少程序卡頓時間
  • 缺點
    • 無法回收循環(huán)引用的對象
    • 資源消耗較大s

標(biāo)記清除
  • 優(yōu)點:
    • 可以回收循環(huán)引用的對象
  • 缺點
    • 空間產(chǎn)生碎片化空間,浪費空間

標(biāo)記整理
  • 優(yōu)點:
    • 減少碎片化空間
  • 缺點:
    • 不會立即回收垃圾對象

3. V8引擎

3.1 認識V8

  • V8是一款主流的 JavaScript 執(zhí)行引擎
  • V8采用即時編譯
  • V8內(nèi)存設(shè)限

即時編譯: 之前很多的JavaScript引擎都需要將源代碼轉(zhuǎn)成字節(jié)碼烙肺,然后再去執(zhí)行纳猪。而對于V8來說,就可以直接將源碼翻譯成我們當(dāng)前可以直接執(zhí)行的機器碼桃笙,所以這個時候的速度是非呈系蹋快。

內(nèi)存設(shè)限: 64位的操作系統(tǒng)下搏明,上限是不超過1.5G鼠锈,對于32位操作系統(tǒng),上限是不超過800M星著。

?為什么有內(nèi)存設(shè)限

  1. V8本身就是為了瀏覽器而制造的购笆,現(xiàn)有的內(nèi)存大小對于網(wǎng)頁來說是足夠使用了
  2. V8內(nèi)部所去實現(xiàn)的垃圾回收機制,采用這個機制是合理的强饮。
官方做個測試

當(dāng)我們的垃圾內(nèi)存達到1.5個G的時候由桌,如果V8采用增量標(biāo)記的算法進行垃圾回收,只需要消耗50毫秒邮丰,而如果采用非增量標(biāo)記的算法進行回收行您,則需要1秒鐘。那么從用戶體驗角度來說剪廉,1秒鐘算很長的時間了娃循,在這里就以1.5個G來為界了。

3.2 V8垃圾回收

V8垃圾回收策略

  • 采用分代回收的思想
  • 內(nèi)存分為新生代斗蒋、老生代
  • 針對不同對象采用不同算法

V8垃圾回收策略圖示

V8中常用GC算法

  • 分代回收
  • 空間復(fù)制
  • 標(biāo)記清除
  • 標(biāo)記整理
  • 標(biāo)記增量

V8內(nèi)存分配

  • V8內(nèi)存空間一分為二
  • 小空間用于存儲新生代對象(32M | 16M)
  • 新生代指的是存活時間較短的對象

什么叫存活時間較短 eg:局部的作用域捌斧,這個局部的作用域當(dāng)中的變量在執(zhí)行完成之后就肯定要去回收


如何回收新生代對象

新生代對象回收實現(xiàn)

  • 回收過程采用復(fù)制算法 + 標(biāo)記整理
  • 新生代內(nèi)存區(qū)分為二個等大小空間 (FROM、TO)
  • 使用空間為From泉沾,空閑空間為To
  • 活動對象存儲于From空間
  • 標(biāo)記整理后將活動對象拷貝至To
  • From與To交換空間完成釋放

回收細節(jié)說明

  • 拷貝過程中可能出現(xiàn)晉升
  • 晉升就是將新生代對象移動至老生代
  • 一輪GC還存活的新生代需要晉升
  • To空間的使用率超過了25%
為什么是25%捞蚂?

因為我們在將來進行回收操作的時候,最終是要吧From的空間和To的空間進行一個交換跷究,也就是說以前的To會變成From姓迅,而From會變成To,也就意味著如果To使用率達到了80%俊马,那么最終它變成活動對象存儲空間后丁存,那么新的對象好像就存不進去了


如何回收老生代對象

老生代對象說明

  • 老生代對象存放在右側(cè)老生代區(qū)域
  • 64位操作系統(tǒng)1.4G,32操作系統(tǒng)700M
  • 老生代對象就是指存活時間較長的對象

老生代對象回收實現(xiàn)

  • 主要采用標(biāo)記清除柴我、標(biāo)記整理增量標(biāo)記算法
  • 首先使用標(biāo)記清除完成垃圾空間的回收
  • 采用標(biāo)記整理進行空間優(yōu)化
  • 采用增量標(biāo)記進行效率優(yōu)化
什么時候進行標(biāo)記整理?

當(dāng)把我們新生代區(qū)域里面的內(nèi)容往我們當(dāng)前這個老生代區(qū)域進行移動時解寝,而且在這個時間節(jié)點上老生代區(qū)域的空間又不足以來存放我們新生代存儲區(qū)所移過來的對象

<font color="red">細節(jié)對比</font>

  • 新生代區(qū)域垃圾回收使用空間換時間
  • 老生代區(qū)域垃圾回收不適合復(fù)制算法

標(biāo)記增量如何優(yōu)化垃圾回收

<font color="red">增量標(biāo)記算法:</font>將一整段的垃圾回收操作,拆分成多個小步艘儒,組合完成整個垃圾回收操作聋伦。我們知道夫偶,當(dāng)垃圾回收工作的時候,會阻塞JS程序執(zhí)行嘉抓,當(dāng)我們需要優(yōu)化垃圾回收的效率時索守,就可以使用增量標(biāo)記算法。

<font color="red">優(yōu)點:</font>讓垃圾回收與程序執(zhí)行可以交替完成抑片,讓時間消耗更合理卵佛,達到效率優(yōu)化的好處。

工作原理:
  • JS 程序執(zhí)行的過程中敞斋,會伴隨著垃圾回收的工作
  • 當(dāng)垃圾回收工作時截汪,需要遍歷對象進行標(biāo)記,此時不需要將所有對象進行標(biāo)記植捎,可以先將直接可達的對象進行標(biāo)記衙解,此時停下標(biāo)記操作
  • 然后讓JS程序執(zhí)行一會,之后焰枢,再讓 GC 機制去做二步的標(biāo)記操作蚓峦,去標(biāo)記那些間接可達的對象
  • 重復(fù)以上兩步,讓程序執(zhí)行和垃圾回收的標(biāo)記操作交替執(zhí)行济锄,來達到優(yōu)化效率和提升用戶體驗的目的
  • 直到標(biāo)記操作完成之后暑椰,最后執(zhí)行垃圾回收

V8垃圾回收總結(jié)

  • V8 是一款主流的JavaScript執(zhí)行引擎
  • V8 內(nèi)存設(shè)置上限
  • V8 采用基于分代回收思想實現(xiàn)垃圾回收
  • V8 內(nèi)存分為新生代和老生代
  • V8 垃圾回收常見的GC算法
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市荐绝,隨后出現(xiàn)的幾起案子一汽,更是在濱河造成了極大的恐慌,老刑警劉巖低滩,帶你破解...
    沈念sama閱讀 219,427評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件召夹,死亡現(xiàn)場離奇詭異,居然都是意外死亡恕沫,警方通過查閱死者的電腦和手機监憎,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,551評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來婶溯,“玉大人枫虏,你說我怎么就攤上這事∨朗” “怎么了?”我有些...
    開封第一講書人閱讀 165,747評論 0 356
  • 文/不壞的土叔 我叫張陵腾它,是天一觀的道長跑筝。 經(jīng)常有香客問我,道長瞒滴,這世上最難降的妖魔是什么曲梗? 我笑而不...
    開封第一講書人閱讀 58,939評論 1 295
  • 正文 為了忘掉前任赞警,我火速辦了婚禮,結(jié)果婚禮上虏两,老公的妹妹穿的比我還像新娘愧旦。我一直安慰自己,他們只是感情好定罢,可當(dāng)我...
    茶點故事閱讀 67,955評論 6 392
  • 文/花漫 我一把揭開白布笤虫。 她就那樣靜靜地躺著,像睡著了一般祖凫。 火紅的嫁衣襯著肌膚如雪琼蚯。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,737評論 1 305
  • 那天惠况,我揣著相機與錄音遭庶,去河邊找鬼。 笑死稠屠,一個胖子當(dāng)著我的面吹牛峦睡,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播权埠,決...
    沈念sama閱讀 40,448評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼榨了,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了弊知?” 一聲冷哼從身側(cè)響起阻逮,我...
    開封第一講書人閱讀 39,352評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎秩彤,沒想到半個月后叔扼,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,834評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡漫雷,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,992評論 3 338
  • 正文 我和宋清朗相戀三年瓜富,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片降盹。...
    茶點故事閱讀 40,133評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡与柑,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出蓄坏,到底是詐尸還是另有隱情价捧,我是刑警寧澤,帶...
    沈念sama閱讀 35,815評論 5 346
  • 正文 年R本政府宣布涡戳,位于F島的核電站结蟋,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏渔彰。R本人自食惡果不足惜嵌屎,卻給世界環(huán)境...
    茶點故事閱讀 41,477評論 3 331
  • 文/蒙蒙 一推正、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧宝惰,春花似錦植榕、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,022評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至汞斧,卻和暖如春夜郁,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背粘勒。 一陣腳步聲響...
    開封第一講書人閱讀 33,147評論 1 272
  • 我被黑心中介騙來泰國打工竞端, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人庙睡。 一個月前我還...
    沈念sama閱讀 48,398評論 3 373
  • 正文 我出身青樓事富,卻偏偏與公主長得像,于是被迫代替她去往敵國和親乘陪。 傳聞我的和親對象是個殘疾皇子统台,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,077評論 2 355

推薦閱讀更多精彩內(nèi)容