從JavaScript的垃圾回收機制談起

javascript垃圾回收機制大家肯定都有所瞭解。網上大部分的文章也都是在講引用計數算法和垃圾回收算法的原理以及這兩者之間的區別。今天咱們不提這個,咱們只提關於老垃圾回收算法和新垃圾回收算法的演變。

一.舊的javascript垃圾回收算法:

我們以V8引擎爲劃分線。v8之前的瀏覽器的垃圾回收算法大概有三類:

1.引用計數(Reference Counting)算法(低版本ie下使用)
2.標記-清除(Mark-Sweep)算法
3.複製(copying)算法

我們先談談引用計數算法。顧名思義,引用計數算法的原理就是跟蹤記錄每個值被引用的次數。當聲明一個變量將一個引用類型賦值給該變量時該值引用次數加1,當這個變量指向另一個時該值的引用次數便減一。當該值引用次數爲0時就會被回收。它的缺點簡單提提,循環引用時會引發內存泄露。
再談談標記-清除算法。當變量進入執行環境的時候,比如函數中聲明一個變量,垃圾回收器將其標記爲“進入環境”,當變量離開環境的時候(函數執行結束)將其標記爲“離開環境”。它的缺點是會產生小的內存碎片,而小的內存碎片再未來有大內存空間需要分配時是無法被利用的。
最後談談複製算法。此算法的出現是爲了解決標記清除算法效率低下的問題,我們來看看原理。首先,此算法會將內存空間分爲兩部分,我們假設爲A區域和B區域。先將所有的對象放置到A區中,在開始進行垃圾回收時,把A區中還需要留下來下次使用的對象轉移到B區,然後將A區中剩餘的對象清空,最後再將B區的對象轉移到A區,以此類推。此算法效率奇高,但是要閒置一半的內存空間,實在是讓人難以接受。

二.V8新生代垃圾回收算法:

V8的GC回收算法主要是將內存空間劃分爲了新生代和老生代,新生代主要採用Scavenge算,而Scavenge算法是基於Cheney算法實現的(Cheney算法就是基於上面我說copying算法);老生代採用的是Mark-Sweep&Mark-Compact算法。

1.新生代:Scavenge算法-Cheney算法.
2.老生代:Mark-Sweep&Mark-Compact算法.

我們先談談新生代裏垃圾回收機制是怎麼運行的。由於它是基於copying算法,那麼原理就很顯然了,它將新生代所佔據的內存空間分成兩部分FORM和TO,當垃圾回收開始時,來檢查A區中的存活對象,然後將這些存貨對象移入TO區中,再釋放FORM區的內存。最後將FORM,TO對調。

Scavenge算法通過犧牲空間換時間的算法非常適合生命週期短的新生代,但是,當一個對象經過多次複製,生命週期較長的時候或則B空間不足的時候,對象會被分配到進入到老生代中,並採用新的算法進行垃圾回收。

那麼老生代是如何運行的呢?
Mark-Sweep算法會在垃圾回收時遍歷老生代空間中所有的存活對象,並標記他們。然後清除掉沒有被標記的對象。而Mark-Compact則是用來處理標記清除後存在的內存碎片問題。它會將活着的對象往內存空間的一端移動,移動完成後直接清除邊界外的內存,以此完成對碎片的回收。

除此之外還需要補充的一點是,對象晉升。其實就是新生代對象晉升到老生代對象的過程。
對象晉升主要發生在FORM空間複製對象到TO空間時期,在這期間主要有兩個判斷條件:

1.是否已經經歷過Scavenge回收
2.TO空間的內存佔用比是否超過25%

滿足其中任意一個條件此對象就會晉升到老生代空間中

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章