《垃圾回收的演算法與實現》作者中村成洋&相川光:高手對話,揭祕GC(圖靈訪談)

劉敏ituring發表於2016-10-24

訪談物件:

中村成洋
Network Applied Communication Laboratory Ltd. 研究員。因為偶然的機會對GC產生濃厚興趣,其本人卻說不清楚為何喜歡GC,當被人追問原因時,總是回答“是緣分”。現在是CRuby的commiter,每天致力於GC的改善。如你所猜,跟Ruby之父——松本行弘是同事。執筆本書的“實現篇”。

個人網站:http://www.narihiro.info/

enter image description here

相川光
遊戲開發者。京都大學學習期間開始研究GC。熱愛GC但討厭打掃,除了GC之外還喜歡咖哩。執筆本書的“演算法篇”。

《垃圾回收的演算法與實現》作者中村成洋&相川光:高手對話,揭祕GC(圖靈訪談)

訪談內容:

點選檢視日文版

《垃圾回收的演算法與實現》深受中國讀者的喜愛,圖靈代表讀者向兩位作者的辛苦付出表示衷心的感謝!我們都知道寫書不僅耗時費力,在出版後還容易遭受同行們的指責。這一點在技術書裡尤為顯著,兩位是出於怎樣的考慮,想要完成這部著作的呢?

中村: 想當年我學習GC那會兒,關於GC公開的資訊並不太多,學起來真是相當費勁。因此,我寫這本書是為了那些像當年的我一樣“想要學習GC!”的讀者,為了讓他們能夠更輕鬆地學習GC。

寫起來真是不容易啊……多虧了合著者、審校和編輯的大力幫助,我才能完成這本作品。現在回眼望去,大部分都是靠著初生牛犢不怕虎的衝勁兒……(笑)

相川: 本書面向的讀者是那些對程式設計有一定了解的人群。為了方便閱讀,我儘可能地縮減了對程式設計基礎知識的介紹,儘可能地對各個演算法進行了深入的剖析。此外,為了讓讀者體會到垃圾回收的有趣之處,我也下了一番功夫。

中國方面已經翻譯了理查德·瓊斯老師的著作《垃圾回收演算法手冊:自動記憶體管理的藝術》,想必也有不少人已經掌握了一些GC相關的知識。本書中還介紹了一些在該書出版時尚未問世的演算法,希望大家能從這些不同的觀點中獲得樂趣。

能否向讀者簡要介紹下GC在程式中的作用?

中村: GC是一種能自動釋放並回收程式中產生的那些看不見的垃圾(不要的記憶體空間)的機制。

相川: 一句話概括的話,GC就是“自動記憶體管理系統”。它是一個能把不再需要的記憶體空間自動釋放和回收的機制。藉助GC,程式設計師可以不用擔心忘記釋放或重複釋放了記憶體空間,可以提高程式設計的效率。

**目前存在的多種GC演算法大都是對標記-清除演算法、引用計數法、複製法的拆分組合。根據您的認識,未來真正意義上的第四種演算法應該是怎樣的?

中村: 第四種演算法啊……這可很難回答啊。我感覺這種演算法應該非常簡單,並且能夠應用於現實世界。就像一下子恍然大悟——“啊!還有這種清掃方法呢!”經常做家務的人或許會比較容易有靈感吧。(笑)

相川: 三種基本演算法問世已經過去了幾十年,這期間完全沒有新的演算法出現。因此,我覺得“真正意義上的第四種演算法”不會那麼簡單地被發明出來。

話說回來,還有一些採用不同於GC標準來進行記憶體管理的方法(比如基於空間的記憶體管理方法)。在不久的將來,如果出現一種全新的GC演算法,估計也是從這類方法的靈感中衍生出來的吧。

很多高階程式語言內部就搭載有GC。這對GC技術研究開發者而言是怎樣的機遇,又有哪些挑戰?

相川: 還沒怎麼普及的時候,人們對GC的要求非常有限,無非是“高速化”“節約記憶體”,等等。近年來,搭載GC的語言被用於多種用途和各種環境,人們對GC的要求也必然變得多樣。像“減少耗電量”“縮減應用程式的中斷時間”等,出現了以往從未有過的高要求。為了滿足這些要求,GC應該還有很大的研究空間。

中村: GC領域是一塊非常複雜且具有專業性的領域,不過世界上把GC作為專業來研究的技術人員卻不多。

比如說,如果大家能用打游擊的形式,時不時寫一些開源的高階程式語言的GC,時不時為GC領域作一些貢獻的話,過不多久,大家也就能光靠GC來餬口了。

記憶體管理和垃圾回收會成為未來程式語言發展時的考慮標準麼?

相川: 我認為有可能,或者可以說,已經成為未來程式語言發展的考慮標準了。只要沒有極其特殊的原因,程式語言都應該統一配備GC。

將GC匯入程式語言,大體上有三種方法:第一種是使用Java和Python等已經安裝了GC的語言來實現程式語言;第二種則是使用像BoehmGC這樣的庫;第三種就是自己來實現了。

從我個人的觀點看,希望大家還是能夠自己來挑戰一次GC的實現。

中村: 對的。有這個可能,確實,記憶體管理和GC已經在逐漸成為未來程式語言發展時的考慮標準了。而且我認為,硬體和OS方面還將會新增一些支援,好讓人們更容易編寫GC。

下面的問題來自讀者實踐過程中遇到的問題。

①程式級的垃圾回收實現問題 (erlang這門語言使用程式級的垃圾回收機制,效率非常高。erlang有一個衍生語言叫elixir,elixir的語法很像ruby,它也使用erlang的垃圾回收機制(基於beam)。您和ruby的作者是同事,對ruby應該很熟悉,能有機會介紹elixir語言的垃圾回收機制嗎?)

中村: Erlang的GC看來相當有意思。據說Erlang在輕量級程式間不存在共享物件,所以可以分程式進行GC。而且物件都是immutable的,因此程式絕對不可能引用物件生成後的新建物件。

從語言規範角度而言,程式只能引用曾經存在過的物件。Erlang就是利用這種特殊性質來高效實現GC複製演算法的。

詳細情況我也不太清楚,這個問題就請各位讀者來研究了。

②.垃圾回收演算法對移動裝置效能的影響問題 (有些ios app使用javascript相關的技術,v8是底層引擎使用垃圾回收演算法釋放資源,但有些手機記憶體很少(比如1G運存的iphone),垃圾回收的頻率會很高。請問這種情況下垃圾回收演算法會影響移動應用體驗嗎?如果想優化體驗,應該如何設定垃圾回收演算法的引數?)

中村: 我認為這取決於應用程式的性質。

如果是高實時性的應用程式(如遊戲等),就需要考慮GC的問題。不過,像是Twitter和Facebook這種實時性低的應用程式,就不用太在意了。

想優化體驗的話,還請了解各種GC的用法,賦予合適的引數。大家可以採用很多方法,例如縮短GC的時間間隔,或是縮小堆的大小……如果情況還不能得到改善,或許就需要考慮GC的問題,在應用程式這邊修改一下程式碼了。

不同情況有不同的解決辦法,所以不能一概而論,不能一口咬定“就這麼解決!”這正是GC的難點所在。

相川: 在分代GC中有很多引數需要調整,例如分代的數量、用於晉升的閾值等。這就需要具體情況具體分析,按照不同程式的特性來相應地調整引數,不過說實話,我這方面的經驗不是很多。關於這方面的知識,建議讀者參照下面的連結。https://docs.oracle.com/cd/E19528-01/820-1613/6nd986vcr/index.html(日文)

③.在資料處理領域,如若資料量很大,特別是T級別的,應該如何選擇GC策略,保證系統穩定、減少GC對程式的影響?

相川: 這也需要根據程式的特性來謹慎地選擇。

我個人認為,對於那些巨大的記憶體空間來說,GC複製演算法會比較有用(因為GC複製演算法相對其他演算法而言缺點要少一些)。在某些情況下,如果採用了GC複製演算法但“垃圾還是較多”,可能就需要採用其他演算法了。

總而言之,選擇的策略很大程度上是受程式動作左右的。

中村: 這個問題的答案也取決於實際資料的型別以及想要達成的目的。

如果是注重實時性的操作,就需要採用在內部執行GC的策略(例如並行GC)。要是像Web應用那樣,不在乎出現一些停頓的話,也可以採用Stop the world的演算法。如果要處理的資料是可以長期存活的資料,那麼即使使用分代GC,減少對處理資料的GC試執行次數,也會有效果的。

④.怎麼看待HotSpot的GC?它與DalvikVM、Rubinius的差異在哪裡?有無優劣之分?

中村: 我認為HotSpot的GC很棒。我對此深感佩服,居然能靈活運用這麼複雜的東西……

GC的演算法各有各的優點和缺點。因此,很難判斷其優劣之分……

HotSpot配備了大量的GC演算法,使用者可以從中隨意選擇。而且HotSpot也為大家準備了豐富的調優選項。就使用者能夠根據用例來進行選擇這一點而言,我認為HotSpot的GC比其他的語言處理程式更出類拔萃。相反地,使用者也會因為選項太多而找不著北……這邊可謂是相當複雜呢。

也有人在研究用機器學習來決定調優引數和GC演算法,不過要實際應用起來似乎並不簡單。

相川: HotSpotVM最先採用了Mostly-Concurrent GC 和G1GC這些最新的演算法。考慮到開發成本中還必須包括直譯器和虛擬機器主體,不得不說這非常值得讚歎。

話說回來,不能單純斷定它就比其他程式設計環境優秀。因為GC的效能很大程度上受應用程式的動作左右。因此,如果大家可以根據應用程式的特性來選擇GC演算法、進行引數的調整的話,說不定就能將GC的潛能發揮到極限。

HotSpotVM有很多GC演算法可供選擇,可以說,比起其他程式設計環境,HotSpotVM更容易將GC的潛能發揮得淋漓盡致。

中村先生為Ruby 2.0新增了Non-recursive Marking 和Bitmap Marking。能否向中國的讀者介紹下Non-recursive Marking 和Bitmap Marking的原理? 目前為Ruby在GC方面的發展在做著哪些努力?

在GC處理過程中會出現函式遞迴的現象,Non-recursive Marking就是用來防止這種情況的。我自己設計了棧結構,實現了把物件分配到棧上進行處理。

Bitmap Marking有點複雜。Ruby採用的是標記清除GC。這個GC一開始會遍歷所有存活的物件,進行標記。 標記操作則會設定物件的header field中的FL_MARK標誌。然後GC會再一次遍歷所有的物件,清除所有已經死亡的物件的標記。問題就在於,這裡破壞了CoW的語義,要標記的所有頁面都Dirty了。

而Bitmap Marking只會把物件的FL_MARK標誌單獨拿出來,作為點陣圖存放在一部分空間裡。這樣既能充分利用CoW的機制,又能優化某些程式(例如在Linux中使用了fork())中記憶體的用量。

現在我已經不再研究Ruby的GC,歸隱山林了……

請兩位老師給有志於加入GC技術開發的後輩們一些規劃、建議?

中村: GC是一個很難找到答案,卻又趣味橫生、充滿挑戰的領域。我認為理論部分很重要,但更重要的是試著親身去研究實現的那些讓人搞不清楚的地方。建議大家可以先由淺入深,之後自己試著實際操作!

相川: GC是一個非常有趣又深奧的主題。大家如果讀了這本書,對這點就應該深有體會。

如果大家能讀一些GC相關的論文,實現GC,跟其他的技術人士討論GC,進一步擴充本書中體驗到的趣味性和奧祕之處,我會感到無上的榮幸。


——更多訪談


更多精彩,加入圖靈訪談微信!

相關文章