垃圾回收算法優缺點對比

img_830c2a85da95ec10021fcb48d4370609.png
image.png

GC之前

說明:該文中的GC算法講解不僅僅局限于某種具體開發語言。

mutator

mutator 是 Edsger Dijkstra 、 琢磨出來的詞,有“改變某物”的意思。說到要改變什么,那就是 GC 對象間的引用關系。不過光這么說可能大家還是不能理解,其實用一句話概括的話,它的實體就是“應用程序”。這樣說就容易理解了吧。GC 就是在這個 mutator 內部精神飽滿地 工作著。

mutator 實際進行的操作有以下 2 種。

  • 生成對象
  • 更新指針

mutator 在進行這些操作時,會同時為應用程序的用戶進行一些處理(數值計算、瀏覽網頁、 編輯文章等)。隨著這些處理的逐步推進,對象間的引用關系也會“改變”。伴隨這些變化會 產生垃圾,而負責回收這些垃圾的機制就是 GC。

活動對象 / 非活動對象

我們將分配到內存空間中的對象中那些能通過 mutator 引用的對象稱為“活動對象”。反 過來,把分配到堆中那些不能通過程序引用的對象稱為“非活動對象”。

根(root)這個詞的意思是“根基”“根底”。在 GC 的世界里,根是指向對象的指針的“起點” 部分。

這些都是能通過 mutator 直接引用的空間。

評價標準

評價 GC 算法的性能時,我們采用以下 4 個標準。

  • 吞吐量
  • 最大暫停時間
  • 堆使用效率
  • 訪問的局部性

其他信息(Java語言為例):JVM解讀-GC(垃圾回收)


1 標記-清除法

優點

①實現簡單

說到 GC 標記 - 清除算法的優點,那當然要數算法簡單,實現容易了。
另外,如果算法實現簡單,那么它與其他算法的組合也就相應地簡單。

②與保守式 GC 算法兼容

后面介紹的保守式 GC 算法中,對象是不能被移動的。因此保守式 GC 算法跟把 對象從現在的場所復制到其他場所的 GC 復制算法與標記 - 壓縮算法不兼容。

而 GC 標記 - 清除算法因為不會移動對象,所以非常適合搭配保守式 GC 算法。事實上,在很多采用保守式 GC 算法的處理程序中也用到了 GC 標記 - 清除算法。

缺點

①碎片化

在 GC 標記 - 清除算法的使用過程中會逐漸產生被細化的分塊,不久后就會導致無數的 小分塊散布在堆的各處。我們稱這種狀況為碎片化(fragmentation)。眾所周知,Windows 的 文件系統也會產生這種現象。

img_6f0119442ac486e3da4376397a0b615b.png
image.png

②分配速度

GC 標記 - 清除算法中分塊不是連續的,因此每次分配都必須遍歷空閑鏈表,找到足夠 大的分塊。最糟的情況就是每次進行分配都得把空閑鏈表遍歷到最后。

另一方面,因為在 GC 復制算法和 GC 標記 - 壓縮算法中,分塊是作為一個連續的內存 空間存在的,所以沒必要遍歷空閑鏈表,分配就能非常高速地進行,而且還能在堆允許范圍 內分配很大的對象。

③與寫時復制技術不兼容

寫時復制技術(copy-on-write)是在 Linux 等眾多 UNIX 操作系統的虛擬存儲中用到的高速化方法。在 Linux 中復制進程,也就是使用 fork() 函數時,大部分內存空間都不會被復制。只是復制進程,就復制了所有內存空間的話也太說不過去了吧。因此,寫時復 制技術只是裝作已經復制了內存空間,實際上是將內存空間共享了。

在各個進程中訪問數據時,能夠訪問共享內存就沒什么問題了。
然而,當我們對共享內存空間進行寫入時,不能直接重寫共享內存。因為從其他程序訪 問時,會發生數據不一致的情況。在重寫時,要復制自己私有空間的數據,對這個私有空間 進行重寫。復制后只訪問這個私有空間,不訪問共享內存。像這樣,因為這門技術是“在寫 入時進行復制”的,所以才被稱為寫時復制技術。

這樣的話,GC 標記 - 清除算法就會存在一個問題 — 與寫時復制技術不兼容。即使沒 重寫對象,GC 也會設置所有活動對象的標志位,這樣就會頻繁發生本不應該發生的復制, 壓迫到內存空間。

2 引用計數的算法

優點

①可即刻回收垃圾

在引用計數法中,每個對象始終都知道自己的被引用數(就是計數器的值)。當被引用數 的值為 0 時,對象馬上就會把自己作為空閑空間連接到空閑鏈表。也就是說,各個對象在變成垃圾的同時就會立刻被回收。

另一方面,在其他的 GC 算法中,即使對象變成了垃圾,程序也無法立刻判別。只有當 分塊用盡后 GC 開始執行時,才能知道哪個對象是垃圾,哪個對象不是垃圾。也就是說,直 到 GC 執行之前,都會有一部分內存空間被垃圾占用。

②最大暫停時間短

在引用計數法中,只有當通過 mutator 更新指針時程序才會執行垃圾回收。也就是說, 每次通過執行 mutator 生成垃圾時這部分垃圾都會被回收,因而大幅度地削減了 mutator 的最 大暫停時間。

③沒有必要沿指針查找

引用計數法和 GC 標記 - 清除算法不一樣,沒必要由根沿指針查找。減少沿指針查找的次數。

缺點

①計數器值的增減處理繁重

在引用計數法中,每當指針更新時,計數器的值都會隨之更新,因此值的增減處理必然會變得繁重。

②計數器需要占用很多位

用于引用計數的計數器最大必須能數完堆中所有對象的引用數。

③實現煩瑣復雜

引用計數的算法本身很簡單,但事實上實現起來卻不容易。如果漏掉了某處,內存管理就無法正確 進行,就會產生 BUG。

④循環引用無法回收

兩個對象互相引用,所以各對象的計數器的值都是 1。但是這些對象 組并沒有被其他任何對象引用。因此想一并回收這兩個對象都不行,只要它們的計數器值都 是 1,就無法回收。

3 GC 復制算法

優點

①優秀的吞吐量

GC 標記 - 清除算法消耗的吞吐量是搜索活動對象(標記階段)所花費的時間和搜索整體 堆(清除階段)所花費的時間之和。

另一方面,因為 GC 復制算法只搜索并復制活動對象,所以跟一般的 GC 標記 - 清除算 法相比,它能在較短時間內完成 GC。也就是說,其吞吐量優秀。

尤其是堆越大,差距越明顯。GC 標記 - 清除算法在清除階段所花費的時間會不斷增加, 但 GC 復制算法就不會產生這種消耗。畢竟它消耗的時間是與活動對象的數量成比例的。

②可實現高速分配

GC 復制算法不使用空閑鏈表。這是因為分塊是一個連續的內存空間。比起 GC 標記 - 清除算法和引用計數法等使用空閑鏈表的分配,GC 復制算法明顯快得多。

③不會發生碎片化

基于算法性質,活動對象被集中安排在 From 空間的開頭對吧。像這 樣把對象重新集中,放在堆的一端的行為就叫作壓縮。在 GC 復制算法中,每次運行 GC 時 都會執行壓縮。

因此 GC 復制算法有個非常優秀的特點,就是不會發生碎片化。也就是說,可以安排分 塊允許范圍內大小的對象。

④與緩存兼容

在 GC 復制算法中有引用關系的對象會被安排在堆里離彼此較近的位置。這種情況有一個優點,那就是 mutator 執行速度極快。這也是借助壓縮來完成的,通過壓縮來把有引用關系的對 象安排在堆中較近的位置。

缺點

①堆使用效率低下

GC 復制算法把堆二等分,通常只能利用其中的一半來安排對象。也就是說,只有一半 堆能被使用。相比其他能使用整個堆的 GC 算法而言,可以說這是 GC 復制算法的一個重大的缺陷。

通過搭配使用 GC 復制算法和 GC 標記 - 清除算法可以改善這個缺點。

②不兼容保守式 GC 算法

GC 標記 - 清除算法有著跟保守式 GC 算法相兼容的優點。因 為 GC 標記 - 清除算法不用移動對象。

另一方面,GC 復制算法必須移動對象重寫指針,所以有著跟保守式 GC 算法不相容的 性質。

③遞歸調用函數

在這里介紹的算法中,復制某個對象時要遞歸復制它的子對象。因此在每次進行復制的 時候都要調用函數,由此帶來的額外負擔不容忽視。大家都知道比起這種遞歸算法,迭代算 法更能高速地執行

此外,因為在每次遞歸調用時都會消耗棧,所以還有棧溢出的可能。

4 GC標記-壓縮算法

優點

①可有效利用堆

在 GC 標記 - 壓縮算法中會執行壓縮,和其他算法相比而言,堆利用效率高。
而且 GC 標記 - 壓縮算法不會出現 GC 復制算法那樣只能利用半個堆的情況。

另一方面,盡管 GC 標記 - 清除算法也能利用整個堆,但因為沒有壓縮的過程,所以會 產生碎片化,不能充分有效地利用堆。

缺點

①壓縮花費計算成本

在 GC 標記 - 清除算法中,清除階段也要搜索整個堆,不過搜索 1 次就夠了。但 GC 標記 - 壓縮算法要搜索 3 次,這樣就要花費約 3 倍的時間,這是一個相當巨大的缺陷,特別是堆越 大,所消耗的成本也就越大。

4 保守式 GC

什么是保守式 GC

簡單來說,保守式 GC(Conservative GC)指的是“不能識別指針和非指針的 GC”。

優點

①語言處理程序不依賴于 GC

保守式 GC 的優點在于容易編寫語言處理程序。處理程序基本上不用在意 GC 就可以編 寫代碼。語言處理程序的實現者即使沒有意識到 GC 的存在,程序也會自己回收垃圾。因此 語言處理程序的實現要比準確式 GC 簡單。

缺點

①識別指針和非指針需要付出成本

②錯誤識別指針會壓迫堆

當存在貌似指針的非指針時,保守式 GC 會把被引用的對象錯誤識別為活動對象。如果 這個對象存在大量的子對象,那么它們一律都會被看成活動對象。因為程序把已經死了的非 活動對象看成了活動對象,所以垃圾對象會嚴重壓迫堆。

③能夠使用的 GC 算法有限

5 分代垃圾回收

優點

①吞吐量得到改善

通過使用分代垃圾回收,可以改善 GC 所花費的時間(吞吐量)。正如 Ungar 所說的那樣:“據實驗表明,分代垃圾回收花費的時間是 GC 復制算法的 1/4。”可見分代垃圾 回收的導入非常明顯地改善了吞吐量。

另一方面,因為老年代 GC 很費時間,所以我們沒法縮短 mutator 的最大暫停時間。關 于使用分代垃圾回收來縮減 mutator 最大暫停時間的方法

缺點

①在部分程序中會起到反作用

對對象會活得很久的程序執行分代垃圾回收,就會產生以下兩個問題。

  • 新生代GC所花費的時間增多
  • 老年代GC頻繁運行

考慮到這兩點,恐怕我們沒法利用到分代垃圾回收的優點,或者就算利用到了,效果也 甚微。

6 增量式垃圾回收

優點

①縮短最大暫停時間

增量式垃圾回收不是一口氣運行 GC,而是和 mutator 交替運行的,因此不會長時間妨礙 到 mutator 的運行。

增量式垃圾回收適合那些比起提高吞吐量,更重視縮短最大暫停時間的應用程序。

②降低了吞吐量

想要優先提高吞吐量,最大暫停時間就會增加;想要優先縮短最大暫停時間, 吞吐量就會惡化。這兩者是一個權衡關系。至于要優先哪一方,則要根據應用程序而定。

參考文獻:《垃圾回收的算法與實現》


歡迎關注 高廣超的簡書博客 與 收藏文章 !
歡迎關注 頭條號:互聯網技術棧 !

個人介紹:

高廣超:多年一線互聯網研發與架構設計經驗,擅長設計與落地高可用、高性能、可擴展的互聯網架構。

本文首發在 高廣超的簡書博客 轉載請注明!

img_31e2e3075b097cabfd9b3643cd9abaa5.png
簡書博客
img_3b1610566b09db3358ca5dcb3e015a52.png
頭條號

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/390817.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/390817.shtml
英文地址,請注明出處:http://en.pswp.cn/news/390817.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

標準C程序設計七---77

Linux應用 編程深入 語言編程標準C程序設計七---經典C11程序設計 以下內容為閱讀: 《標準C程序設計》(第7版) 作者:E. Balagurusamy(印), 李周芳譯 清華大學出版社…

leetcode 1190. 反轉每對括號間的子串

題目 給出一個字符串 s(僅含有小寫英文字母和括號)。 請你按照從括號內到外的順序,逐層反轉每對匹配括號中的字符串,并返回最終的結果。 注意,您的結果中 不應 包含任何括號。 示例 1: 輸入&#xff1a…

yolo人臉檢測數據集_自定義數據集上的Yolo-V5對象檢測

yolo人臉檢測數據集計算機視覺 (Computer Vision) Step by step instructions to train Yolo-v5 & do Inference(from ultralytics) to count the blood cells and localize them.循序漸進的說明來訓練Yolo-v5和進行推理(來自Ultralytics )以對血細胞進行計數并將其定位。 …

oauth2-server-php-docs 授權類型

授權碼 概觀 在Authorization Code交付式時使用的客戶端想要請求訪問受保護資源代表其他用戶(即第三方)。這是最常與OAuth關聯的授予類型。 詳細了解授權碼 用例 代表第三方來電履行 創建一個實例OAuth2\GrantType\AuthorizationCode并將其添加到您的服務…

flask框架視圖和路由_角度視圖,路由和NgModule的解釋

flask框架視圖和路由Angular vs AngularJS (Angular vs AngularJS) AngularJS (versions 1.x) is a JavaScript-based open source framework. It is cross platform and is used to develop Single Page Web Application (SPWA). AngularJS(版本1.x)是一個基于JavaScript的開源…

NGUI EventDelagate事件委托

using System.Collections; using System.Collections.Generic; using UnityEngine;public class BUttonClick : MonoBehaviour {public UIButton button_01;void Start(){if (button_01 null){Debug.Log("button組件丟失了");}else{//首先將腳本中的ClicktheButton…

leetcode 461. 漢明距離(位運算)

兩個整數之間的漢明距離指的是這兩個數字對應二進制位不同的位置的數目。 給出兩個整數 x 和 y&#xff0c;計算它們之間的漢明距離。 注意&#xff1a; 0 ≤ x, y < 231. 示例:輸入: x 1, y 4輸出: 2解釋: 1 (0 0 0 1) 4 (0 1 0 0)↑ ↑上面的箭頭指出了對應二進…

圖深度學習-第2部分

有關深層學習的FAU講義 (FAU LECTURE NOTES ON DEEP LEARNING) These are the lecture notes for FAU’s YouTube Lecture “Deep Learning”. This is a full transcript of the lecture video & matching slides. We hope, you enjoy this as much as the videos. Of cou…

Linux下 安裝Redis并配置服務

一、簡介 1、 Redis為單進程單線程模式&#xff0c;采用隊列模式將并發訪問變成串行訪問。 2、 Redis不僅僅支持簡單的k/v類型的數據&#xff0c;同時還提供list&#xff0c;set&#xff0c;zset&#xff0c;hash等數據結構的存儲。 3、 Redis支持數據的備份&#xff0c;即mas…

大omega記號_什么是大歐米茄符號?

大omega記號Similar to big O notation, big Omega(Ω) function is used in computer science to describe the performance or complexity of an algorithm.與大O表示法相似&#xff0c;大Omega(Ω)函數在計算機科學中用于描述算法的性能或復雜性。 If a running time is Ω…

leetcode 477. 漢明距離總和(位運算)

theme: healer-readable 題目 兩個整數的 漢明距離 指的是這兩個數字的二進制數對應位不同的數量。 計算一個數組中&#xff0c;任意兩個數之間漢明距離的總和。 示例: 輸入: 4, 14, 2 輸出: 6 解釋: 在二進制表示中&#xff0c;4表示為0100&#xff0c;14表示為1110&…

什么是跨域及跨域請求資源的方法?

1、由于瀏覽器同源策略&#xff0c;凡是發送請求url的協議、域名、端口三者之間任意一與當前頁面地址不同即為跨域。 2、跨域請求資源的方法&#xff1a; (1)、porxy代理(反向服務器代理) 首先將用戶發送的請求發送給中間的服務器&#xff0c;然后通過中間服務器再發送給后臺服…

量子信息與量子計算_量子計算為23美分。

量子信息與量子計算On Aug 13, 2020, AWS announced the General Availability of Amazon Braket. Braket is their fully managed quantum computing service. It is available on an on-demand basis, much like SageMaker. That means the everyday developer and data scie…

全面理解Java內存模型

Java內存模型即Java Memory Model&#xff0c;簡稱JMM。JMM定義了Java 虛擬機(JVM)在計算機內存(RAM)中的工作方式。JVM是整個計算機虛擬模型&#xff0c;所以JMM是隸屬于JVM的。 如果我們要想深入了解Java并發編程&#xff0c;就要先理解好Java內存模型。Java內存模型定義了多…

React Native指南

React本機 (React Native) React Native is a cross-platform framework for building mobile applications that can run outside of the browser?—?most commonly iOS and Android applicationsReact Native是一個跨平臺框架&#xff0c;用于構建可在瀏覽器外部運行的移動…

leetcode 1074. 元素和為目標值的子矩陣數量(map+前綴和)

給出矩陣 matrix 和目標值 target&#xff0c;返回元素總和等于目標值的非空子矩陣的數量。 子矩陣 x1, y1, x2, y2 是滿足 x1 < x < x2 且 y1 < y < y2 的所有單元 matrix[x][y] 的集合。 如果 (x1, y1, x2, y2) 和 (x1’, y1’, x2’, y2’) 兩個子矩陣中部分坐…

失物招領php_新奧爾良圣徒隊是否增加了失物招領?

失物招領phpOver the past couple of years, the New Orleans Saints’ offense has been criticized for its lack of wide receiver options. Luckily for Saints’ fans like me, this area has been addressed by the signing of Emmanuel Sanders back in March — or has…

教你分分鐘使用Retrofit+Rxjava實現網絡請求

擼代碼之前&#xff0c;先簡單了解一下為什么Retrofit這么受大家青睞吧。 Retrofit是Square公司出品的基于OkHttp封裝的一套RESTful&#xff08;目前流行的一套api設計的風格&#xff09;網絡請求框架。它內部使用了大量的設計模式&#xff0c;以達到高度解耦的目的&#xff1b…

線程與進程區別

一.定義&#xff1a; 進程&#xff08;process&#xff09;是一塊包含了某些資源的內存區域。操作系統利用進程把它的工作劃分為一些功能單元。 進程中所包含的一個或多個執行單元稱為線程&#xff08;thread&#xff09;。進程還擁有一個私有的虛擬地址空間&#xff0c;該空間…

基本SQL命令-您應該知道的數據庫查詢和語句列表

SQL stands for Structured Query Language. SQL commands are the instructions used to communicate with a database to perform tasks, functions, and queries with data.SQL代表結構化查詢語言。 SQL命令是用于與數據庫通信以執行任務&#xff0c;功能和數據查詢的指令。…