您好,登錄后才能下訂單哦!
這篇文章將為大家詳細講解有關nodejs垃圾回收的案例分析,小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。
nodejs的垃圾回收機制是由v8引擎自動管理的。
nodejs的內存限制
在一般的后端語言(php)來說,內存的使用上是沒有限制的,但對于nodejs來說只能使用系統的部分----64位系統為1.4G,32位系統位0.7G。這時如果你要處理個3G文件進行數據分析,即使系統的內存為8G,在該nodejs進程內存還是會溢出。
造成上面這個問題主要是因為nodejs是基于v8的,nodejs是通過v8自己的方式來管理內存的。那v8為什么要限制堆內存的大小呢?原因有2:
1、表層原因:v8是為瀏覽器設計的,不大可能遇到大內存的情景。
2.深層原因:v8垃圾回收機制的限制。以1.5G的堆內存為例,v8做一次小的垃圾回收需要50ms,做一次非增量的垃圾回收要1s。垃圾回收時會引起js的線程的暫停,在這樣的時間花銷下,應用的性能、響應能力會直線下降。
內存限制是可以打開的:
--max-old-space-size(老生代)
--max-new-space-size(新生代)
v8堆內存大小 = 老生代 + 新生代
v8垃圾回收機制
v8垃圾回收主要是基于分代式垃圾回收機制。按對象的存活時間將內存的垃圾回收進行不同的分代,分別對不同的分代內存進行不同的算法。
新生代--->存活時間較短的對象
老生代--->存活時間較長或常駐內存的對象
上面也說過,nodejs堆內存的大小是新生代內存空間加上老生代內存空間。
新生代算法
新生代主要是通過scavenge算法進行垃圾回收。
這是一種采用復制的方式來實現垃圾回收,將堆內存一分為二,每個空間稱為semispace。在這2個semispace空間中,只有一個處于使用中(稱為from空間),另一個處于空閑中(稱為to空間)。開始分配時首先從from空間開始,當開始垃圾回收時,也是從from空間開始檢查存活對象,把存活對象復制到to空間,而非存活對象占用的空間就會被釋放。完成復制后,from空間和to空間角色對調。
從上面的過程可以知道,scavenge的缺點就是只使用了一半的堆內存,犧牲空間獲取時間。
老生代通過mark-sweep、mark-comopact算法。
mark-sweep標記清除,分為標記、清除2個階段。mark-sweep先在標記階段遍歷堆內存中的所有對象,并標記存活的對象;在清除階段把沒有被標記的對象清除。可以看出,scavenge只復制存活的對象,mark-sweep只清理死亡的對象。因為在新生代中存活的對象占用小部分,而在老生代中死亡對象占用小部分,這是這2中算法高效的原因。
Mark-compact標記整理,mark-sweep中會出現一個問題,在回收后,對內存會出現不連續的狀態(內存碎片)。內存碎片會對后續的內存分配造成影響,因為會有這樣一種情況:需要分配個大內存,而所有內存碎片都無法完成分配,這會提前觸發垃圾回收,而這個回收時不必要的。Mark-compact是在Mark-sweep基礎上演變而來的,它主要區別在于:對象被標記后,在整理的過程中會將存活的對象都往一端移動,移動完成后直接清除。
小結:在正常的使用過程中,v8的內存限制還是夠用的,但nodejs的垃圾回收、單線程還是會影響性能。想要高性能,需要讓垃圾回收盡量小。在實際的開發中要老生代對象的使用,如實現web服務的會話(session),一般會通過內存來存儲(數組),在訪問量大的情況下會導致老生代對象劇增,有可能造成溢出。如果要處理大內存的數據,比如讀取3G的文件,我們會通過可讀流的pipe()方法,這樣就不會受到v8內存的限制影響,提高了nodejs程序的健壯性。
關于“nodejs垃圾回收的案例分析”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,使各位可以學到更多知識,如果覺得文章不錯,請把它分享出去讓更多的人看到。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。