Node內存機制

前言

Node是以V8作爲引擎進行開發,所以內存控制也要考慮V8的因素,V8中對內存進行了限制,主要原因在於在瀏覽器運行並不需要這麼大的內存分配,每開一個標籤頁就是一個V8實例,限制的內存遠遠大於所需內存了,另外一點就是在進行垃圾回收時也是非常耗時的,如果內存較多,那麼佔用JavaScript線程的時間就會相對變長,所以限制V8的內存使用是合理的。但是在服務端,我們仍然會存在一些大內存操作的時候,使用process.memoryUsage()可以查看內存使用情況。在一些極端情況下可以設置分配更多的內存空間。

新生代和老生代

Node內存管理採用分代管理的機制,將內存分爲新生代老生代兩種,新生代對象就是那些存活時間短的對象,老生代對象就是存活時間長的對象。在進行垃圾回收時,並沒有一種算法能夠針對不同情況達到最好的回收機制。所以Node採用分代處理的機制管理內存。在Node中爲新生代對象分配的單個區域(reserve_semispace_size)內存空間爲16MB(64位)和8MB(32位),新生代管理需要兩個區域進行管理,所以爲32MB(64位)和16MB(32位)。爲老生代分配的內存空間(max_old_generator_size)爲1400MB(64位)和700MB(32位)。所以能夠使用的總空間爲
4 * reserve_semispace_size + max_old_generator_size = 1464MB(64位),大約爲1.4G,32位同理

爲什麼是4倍的reserve_semispace_size不太瞭解,按照意思應該是2倍的

垃圾回收機制

scavenge算法

新生代對象採用scavenge算法進行垃圾回收,主要原理在於對新生代內存空間平分爲兩份(reserve_semispace_size),一份爲From區域,一份爲To區域,對象從From區域向To區域做複製操作,存活對象會複製成功,死對象不會進行復制操作,最後刪除那些死對象。操作完畢過後將From和To對調,便於進行下一次複製操作。scavenge算法適用於新生代對象的優勢在於,新生代內存空間中存活對象相對較少,複製操作較少。

判斷新生代對象與老生代對象的方法在於是否經歷過scavenge算法,新生代對象如果經歷過scavenge算法後沒有被清除,則將其轉化爲老生代對象

標記清除

老生代對象內存空間採用標記請求的方式進行垃圾回收,垃圾回收器運行時會將活對象打上標記,最後清除那些沒有標記的對象。標記清除適用於老生代內存空間的原因在於老生代對象中死對象較少。標記清除的缺陷在於內存碎片較多,因爲按順序分配的內存空間可能中間一些零碎空間被清除,這些空間不能得以使用,另外一種算法(Mark-Compat)就是在每次標記清除後對內存空間進行平移,充分利用零碎空間。但是Node在考慮性能原因採用標記清除的方式,在有大對象、零碎空間不能得以利用時會使用Mark-Compat算法

增量標記

在運行垃圾回收機制時爲了避免JavaScript運行邏輯與處理垃圾時不一致的情況,所以在進行垃圾回收時會將應用邏輯停下來。在新生代處理中由於活對象較少的原因基本不佔用時間,所以不會有什麼影響。但是老生代內存空間中活對象多,本身內存空間大,存活對象的標記、整理、死對象的清除等都需要大量的時間,所以Node採用增量標記的方式進行優化,將標記變爲一步一步進行,標記一會,然後將處理交給應用邏輯,然後在進行標記

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