【圖解篇】前端內(nèi)存管理

前端為什么要關(guān)注內(nèi)存

  • 防止占用內(nèi)存過大超燃,造成頁面卡頓芍瑞,甚至無響應(yīng)
  • Node.js 使用 V8 引擎,內(nèi)存管理對于服務(wù)端至關(guān)重要皮胡,因為服務(wù)端的持久性痴颊,內(nèi)存更容易積累造成內(nèi)存溢出

js 垃圾回收機制

js 使用垃圾回收機制自動管理內(nèi)存,這種方式的利弊都很明顯屡贺。

  • 優(yōu)勢: 可以大幅簡化程序中都內(nèi)存管理代碼蠢棱,減輕開發(fā)者的負擔,同時也減少長時間運轉(zhuǎn)造成的內(nèi)存泄漏問題
  • 劣勢: 意味著開發(fā)者無法掌控內(nèi)存管理甩栈,我們無法強迫其進行垃圾回收泻仙,進行管理

下面簡單介紹一下 js 的幾種垃圾回收策略:

引用計數(shù)

主要是IE8 以下的瀏覽器使用,現(xiàn)代瀏覽器都棄用了這種方式量没,這里只做簡單介紹玉转。

基本原理就是,記錄跟蹤每個值被引用的次數(shù)殴蹄,被引用一次被引用次數(shù)就加一究抓,被釋放就減一,為零時饶套,就釋放改值所占內(nèi)存漩蟆。

標記清除

主流瀏覽器使用垃圾回收機制。

當變量進入環(huán)境(例如妓蛮,在函 數(shù)中聲明一個變量)時怠李,就將這個變量標記為“進入環(huán)境”。從邏輯上講,永遠不能釋放進入環(huán)境的變量所占用的內(nèi)存捺癞,因為只要執(zhí)行流進入相應(yīng)的環(huán)境夷蚊,就可能會用到它們。

而當變量離開環(huán)境時髓介,則將其 標記為“離開環(huán)境”惕鼓。 可以使用任何方式來標記變量。比如唐础,可以通過翻轉(zhuǎn)某個特殊的位來記錄一個變量何時進入環(huán)境箱歧, 或者使用一個“進入環(huán)境的”變量列表及一個“離開環(huán)境的”變量列表來跟蹤哪個變量發(fā)生了變化。

function test(){
    var a = 10;    //被標記"進入環(huán)境"
    var b = "hello";    //被標記"進入環(huán)境"
}
test(); // 執(zhí)行完畢后之后一膨,a和b又被標記"離開環(huán)境"呀邢,被回收

說到底,如何標記變量其實并不重要豹绪,關(guān)鍵在于采取什么策略价淌。 垃圾收集器在運行的時候會給存儲在內(nèi)存中的所有變量都加上標記(當然,可以使用任何標記方式)瞒津。

然后蝉衣,它會去掉環(huán)境中的變量以及被環(huán)境中的變量引用的變量的標記。而在此之后再被加上標記 的變量將被視為準備刪除的變量巷蚪,原因是環(huán)境中的變量已經(jīng)無法訪問到這些變量了病毡。

最后,垃圾收集器完成內(nèi)存清除工作屁柏,銷毀那些帶標記的值并回收它們所占用的內(nèi)存空間剪验。

環(huán)境可以理解為我們的作用域,但是全局作用域的變量只會在頁面關(guān)閉才會銷毀前联。

V8 內(nèi)存控制

V8 的內(nèi)存限制

在 Node 中只能使用部分內(nèi)存,64位系統(tǒng)下約為1.4GB娶眷,32位系統(tǒng)下約為0.7GB似嗤,在這種限制下,將會導致 Node 無法操作大內(nèi)存對象届宠,比如將一個 2GB 的文件讀入內(nèi)存烁落,即使物理內(nèi)存有64 GB,也沒有辦法完成豌注,這個時候我們可以使用 Buffer 類伤塌,來完成大內(nèi)存文件的讀取。

造成這個問題的主要原因: Node 基于 V8 構(gòu)建轧铁,而 V8 的這套內(nèi)存管理機制主要是在瀏覽器中使用每聪,完全可以滿足前端頁面中的所有需求,但是在 Node 中卻限制了開發(fā)者隨心所欲使用大內(nèi)存的想法。

V8 的垃圾回收機制

V8 的垃圾回收策略主要基于分代式垃圾回收機制药薯。主要將內(nèi)存分為新生代和老生代兩代绑洛。

圖片

新生代空間(Young Generaion)

特點:

  • 管理對象存活時間較短
  • 占用空間比老生代空間小很多
  • 垃圾回特別頻繁

新生代空間的垃圾回收采用Scavenge 算法,其工作原理如下

  1. 將新生代空間分為兩個空間童本,稱為semispace真屯,處于使用狀態(tài)的叫做 From 空間,處于閑置的叫 To 空間穷娱,當我們分配對象時绑蔫,先是在 From 空間中進行分配。
圖片
  1. 開始垃圾回收時泵额,會檢查 From 空間中的存活對象配深,這些存活對象將被復(fù)制到 To 空間中,然后釋放 From 空間中的內(nèi)存梯刚。
圖片
圖片
  1. From 空間與 To 空間對換
圖片

從上面的過程我們可以看到凉馆,Scavenge 算法是典型的犧牲空間換取時間的算法。缺點是只能使用堆內(nèi)存中的一半亡资,優(yōu)點是在時間效率上有優(yōu)異的表現(xiàn)澜共。

老生代空間( OldGeneraion)

在新生代空間中生命周期較長的對象會被復(fù)制到老生代空間中,這個過程叫晉升锥腻。對象晉升的條件主要有兩個:

  1. 對象是否經(jīng)歷過一次 Scavenge 回收嗦董。 對象從 From 空間復(fù)制到 To 空間時,會檢查它的內(nèi)存地址來判斷這個對象是否已經(jīng)經(jīng)歷過一次 Scavenge 回收瘦黑。如果經(jīng)歷過京革,就直接復(fù)制到老生代空間中,而不是 To 空間幸斥。
  2. To 空間的內(nèi)存使用占比是否超過 To 空間的 25%匹摇。 對象從 From 空間復(fù)制到 To 空間時,發(fā)現(xiàn) To 空間的內(nèi)存占比已經(jīng)超過限制甲葬。因為To 空間將會變成 From空間廊勃,為了不影響后續(xù)的內(nèi)存分配,會直接晉升到老生代空間中经窖。

對于老生代空間坡垫,由于存活對象占比較大,再采用Scavenge的方式會有兩個問題:

  1. 存活對象比較多画侣,復(fù)制存活對象的效率會很低
  2. 要拆分兩個 semispace 空間冰悠,比較浪費

為此,老生代中主要采用標記清除(Mark-Sweep)標記整理(Mark-Compact)相結(jié)合的方式進行垃圾回收配乱,其工作原理如下

  • 在標記階段遍歷堆中的所有對象溉卓,并標記活著的對象皮迟,在隨后的清除階段中,只清除沒有被標記的對象的诵。標記后的示意圖如下:
圖片

黃色部分為標記活躍的對象万栅,深灰色部分為標記死亡的對象。

標記清除(Mark-Sweep)最大的問題在于西疤,清除標記死亡的對象后烦粒,內(nèi)存不連續(xù),這種碎片空間會對后續(xù)的內(nèi)存分配造成問題代赁。

  • 為了解決內(nèi)存碎片的問題扰她,標記整理(Mark-Compact)被提出來。它會在標記完成后芭碍,將存活的對象移動到一端徒役,然后釋放存活對象這一端之外的空間。
圖片
圖片

增量標記(Incremental Marking)

在進行上面 V8垃圾回收操作的時候窖壕,需要將應(yīng)用邏輯暫停忧勿,但是由于老生代空間很大,且存活對象很多瞻讽,為了避免長時間的停頓鸳吸,將原本一次性完成的操作改為增量標記,即拆分為許多小“步進”速勇,沒做完一次“步進”晌砾,讓應(yīng)用邏輯執(zhí)行一會兒,交替執(zhí)行烦磁,直到垃圾回收執(zhí)行完成养匈。

參考文章:

  1. 《Javascript 高級程序設(shè)計》
  2. 《深入淺出 Node.js》
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市都伪,隨后出現(xiàn)的幾起案子呕乎,更是在濱河造成了極大的恐慌,老刑警劉巖陨晶,帶你破解...
    沈念sama閱讀 211,561評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件楣嘁,死亡現(xiàn)場離奇詭異,居然都是意外死亡珍逸,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,218評論 3 385
  • 文/潘曉璐 我一進店門聋溜,熙熙樓的掌柜王于貴愁眉苦臉地迎上來谆膳,“玉大人,你說我怎么就攤上這事撮躁∈。” “怎么了?”我有些...
    開封第一講書人閱讀 157,162評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長杨帽。 經(jīng)常有香客問我漓穿,道長,這世上最難降的妖魔是什么注盈? 我笑而不...
    開封第一講書人閱讀 56,470評論 1 283
  • 正文 為了忘掉前任晃危,我火速辦了婚禮,結(jié)果婚禮上老客,老公的妹妹穿的比我還像新娘僚饭。我一直安慰自己,他們只是感情好胧砰,可當我...
    茶點故事閱讀 65,550評論 6 385
  • 文/花漫 我一把揭開白布鳍鸵。 她就那樣靜靜地躺著,像睡著了一般尉间。 火紅的嫁衣襯著肌膚如雪偿乖。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,806評論 1 290
  • 那天哲嘲,我揣著相機與錄音贪薪,去河邊找鬼。 笑死撤蚊,一個胖子當著我的面吹牛古掏,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播侦啸,決...
    沈念sama閱讀 38,951評論 3 407
  • 文/蒼蘭香墨 我猛地睜開眼槽唾,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了光涂?” 一聲冷哼從身側(cè)響起庞萍,我...
    開封第一講書人閱讀 37,712評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎忘闻,沒想到半個月后钝计,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,166評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡齐佳,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,510評論 2 327
  • 正文 我和宋清朗相戀三年私恬,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片炼吴。...
    茶點故事閱讀 38,643評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡本鸣,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出硅蹦,到底是詐尸還是另有隱情荣德,我是刑警寧澤闷煤,帶...
    沈念sama閱讀 34,306評論 4 330
  • 正文 年R本政府宣布,位于F島的核電站涮瞻,受9級特大地震影響鲤拿,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜署咽,卻給世界環(huán)境...
    茶點故事閱讀 39,930評論 3 313
  • 文/蒙蒙 一近顷、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧艇抠,春花似錦幕庐、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,745評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至絮重,卻和暖如春冤寿,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背青伤。 一陣腳步聲響...
    開封第一講書人閱讀 31,983評論 1 266
  • 我被黑心中介騙來泰國打工督怜, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人狠角。 一個月前我還...
    沈念sama閱讀 46,351評論 2 360
  • 正文 我出身青樓号杠,卻偏偏與公主長得像,于是被迫代替她去往敵國和親丰歌。 傳聞我的和親對象是個殘疾皇子姨蟋,可洞房花燭夜當晚...
    茶點故事閱讀 43,509評論 2 348

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