Chrome所使用的開源JavaScript引擎V8,使用了新的垃圾回收器(Garbage Collector)Orinoco,除了具一般垃圾回收器的功能外,Orinoco還有平行(Parallel)、並行(Concurrent),且具漸增(Incremental)回退功能,能大幅降低應用程式延遲問題。

一般垃圾收集器的基本任務,會辨識物件存活,一旦物件過期,垃圾收集器便著手回收,並重新使用物件占用的記憶體,進階的功能還會對記憶體進行壓縮或是去碎片化。這些工作可以依序執行,或是任意交錯進行。

V8中會把記憶體堆積分為新生世代(Generation)與年老世代,新生世代又分為托兒所(Nursery)與中間(Intermediate)兩個子代。物件分配最先進到托兒所,當在第一次的垃圾收集中存活下來,仍然被算作新生世代,但會從托兒所移往中間世代,並於下一次垃圾收集存活,被移往老年世代。在V8中有兩種垃圾回收器,主要垃圾回收器從整個堆積(Heap)中收集垃圾,而次要垃圾回收器則收集新生世代的垃圾。

官方提到,目前衡量垃圾回收花費的時間,是主執行緒在執行垃圾收集時所暫停的時間。Orinoco是一個垃圾收集專案的代號,V8團隊為其垃圾收集器,新增一系列垃圾收集最佳化演算法,以釋放主執行緒,避免Chrome發生明顯的停頓。新的垃圾收集器主要使用三種技術,包含平行、漸增以及並行。

垃圾收集器的平行執行,是讓主執行緒以及幫手執行緒分擔差不多的垃圾收集工作,雖然主執行緒仍需要暫停執行JavaScript,但是總暫停時間會是,原本暫停時間除以參與工作的執行緒數,當然會有一些同步的成本,但是分攤下來暫停的時間仍然會比原本短得多,官方提到,平行執行是三種技術實現最簡單的一種。

漸增技術是讓主執行緒間歇性的執行少量的垃圾回收工作,讓主執行緒一次進行一部分的工作,這樣主執行緒就不再需要完全停下來進行垃圾回收,官方提到,這個比平行執行還更加困難,因為JavaScript要在每個漸增工作區段執行,這代表記憶體堆積的狀態已經改變,可能使先前的漸增工作完全無效。雖然這個方法不會減少主執行緒花費在垃圾收集的時間,但是卻能有效解決主執行緒延遲。

第三個也是最困難的技術是並行執行,是當主執行緒在持續執行JavaScript時,讓幫手執行緒在背景進行垃圾收集。官方解釋,之所以這是最困難的技術,因為JavaScript堆積上的所有內容,現在隨時都可能會變更,導致之前完成的工作失效,且主執行緒和幫手執行緒存在讀寫競爭。不過,好處是主執行緒可以無後顧之憂的自由執行JavaScript。

現在V8的主要垃圾收集器,當堆積接近動態計算限制的時候,便會啟動並行標記任務,在主行緒執行JavaScript的時候,每個幫手執行緒對分配的物件,進行追蹤並完成標記,最後主執行緒才會開始暫停,重新掃描一次Root確保存活的物件都被上了標記,並與數個幫手執行緒開始進行平行壓縮以及更新指標,而這個過程主行緒仍然可以再穿插執行JavaScript。

而負責進行新生世代垃圾收集工作的次要垃圾收集器,現在也能夠平行收集垃圾,並跨幫手執行緒地分散作業,對被分派到且歷經第一次垃圾收集存活的物件,執行搬移(Evacuate)集中的工作。

新的垃圾回收器大幅改善了Chrome暫停時間、延遲與頁面載入緩慢的問題,讓動畫、頁面滾動和使用者互動更加順暢,具平行執行功能的次要垃圾收集器,能夠減少20%到50%主執行緒進行新生世代垃圾回收的時間成本,而且並行執行標記與清掃記憶體,可以減少WebGL遊戲暫停時間達50%。官方提到,他們的工作還沒結束,Chrome中的渲染器Blink還有一個垃圾回收器Oilpan,他們要將Orinoco的技術移植過去。

官方特別提到,雖然開發人員在撰寫JavaScript程式的時候,不需要考慮垃圾收集,但是了解內部運作將有幫助提升記憶體使用,有效應用良好的程式開發範式。

熱門新聞

Advertisement