對(duì)象
在GC的世界中努潘,對(duì)象表示的是“通過應(yīng)用程序利用的數(shù)據(jù)的集合”懂牧。對(duì)象配置在內(nèi)存空間里。GC根據(jù)情況將配置好的對(duì)象進(jìn)行移動(dòng)或銷毀操作皱坛。因此编曼,對(duì)象是GC的基本單位。
一般來說剩辟,對(duì)象由頭( header)和域( field)構(gòu)成掐场。在 對(duì)象 內(nèi)部,頭之后存在1個(gè)及1個(gè)以上的域抹沪。
- 頭:對(duì)象中保存對(duì)象本身信息的部分稱為“頭”刻肄。頭主要含有以下信息:對(duì)象的大小和對(duì)象的種類。此外融欧,頭中事先存有運(yùn)行 GC所需的信息敏弃,根據(jù)GC算法的不同,信息也不同噪馏;
- 域:對(duì)象使用者在對(duì)象中可訪問的部分稱為“域”麦到。對(duì)象使用者會(huì)引用或替換對(duì)象的域值绿饵,而基本上無法直接更改頭的信息。域中的數(shù)據(jù)類型大致分為指針和非指針兩種瓶颠;
堆
mutator(應(yīng)用程序)實(shí)際進(jìn)行的操作包括生成對(duì)象和更新指針兩種拟赊。mutator在進(jìn)行這些操作時(shí),會(huì)同時(shí)為應(yīng)用程序的用戶進(jìn)行一些處理粹淋。隨著這些處理的逐步推進(jìn)吸祟,對(duì)象間的引用關(guān)系也會(huì)“ 改變”。伴隨這些變化會(huì)產(chǎn)生垃圾桃移,而負(fù)責(zé)回收這些垃圾的機(jī)制就是GC屋匕。
在開始執(zhí)行mutator前,GC要分配用于堆的內(nèi)存空間借杰。一旦開始執(zhí)行 mutator过吻,程序就會(huì)按照mutator的要求在堆中存放對(duì)象。等到堆被對(duì)象占滿 后蔗衡,GC就會(huì)啟動(dòng)纤虽,從而分配可用空間。如果不能分配足夠的可用空間绞惦,一般情況下就要擴(kuò)大堆逼纸。
將分配到內(nèi)存空間中的對(duì)象中那些能通過mutator引用的對(duì)象稱為“活動(dòng)對(duì)象”。反過來翩隧,把分配到堆中那些不能通過程序引用的對(duì)象稱為“ 非活動(dòng)對(duì)象”樊展。非活動(dòng)對(duì)象就稱為“垃圾”呻纹。
分塊( chunk)指的是為利用對(duì)象而事先準(zhǔn)備出來的空間堆生。初始狀態(tài)下,堆被 一個(gè)大的分塊所占據(jù)雷酪。然后淑仆,程序會(huì)根據(jù)mutator的要求把這個(gè)分塊分割成合適的大小,作為活動(dòng)對(duì)象使用哥力≌岬。活動(dòng)對(duì)象不久后會(huì)轉(zhuǎn)化為垃圾被回收。此時(shí)吩跋,這部分被回收的內(nèi)存空間再次成為分塊寞射,為下次被利用做準(zhǔn)備。也就是說锌钮,內(nèi)存里的各個(gè)區(qū)塊都重復(fù)著分塊→活動(dòng)對(duì)象→垃圾(非活動(dòng)對(duì)象)→分塊→ …… 這樣的過程桥温。
根
根是指向?qū)ο蟮闹羔樀摹?起點(diǎn)” 部分。
1 $ obj = Object.new
2 $ obj.field1 = Object.new
其中$obj是全局變量梁丘,執(zhí)行完侵浸,全局變量空間及堆如下圖:
GC把上述這樣可以直接或間接從全局變量空間中引用的對(duì)象視為活動(dòng)對(duì)象旺韭。
與全局變量空間相同,我們也可以通過mutator直接引用調(diào)用棧(call stack)和寄存器掏觉。也就是說区端,調(diào)用棧、寄存器以及全局變量空間都是根澳腹。
評(píng)價(jià)標(biāo)準(zhǔn)
評(píng)價(jià)GC算法的性能時(shí)织盼,采用以下4個(gè)標(biāo)準(zhǔn):
-
吞吐量
吞吐量( throughput)指的是“在單位時(shí)間內(nèi)的處理能力”。如下圖酱塔,整個(gè)執(zhí)行過程中悔政,GC啟動(dòng)了三次,總花費(fèi)時(shí)間為(A+B+C)延旧,堆大小為HEAP_SIZE谋国,即在大小為HEAP_SIZE的堆上進(jìn)行內(nèi)存管理,需要花費(fèi)的時(shí)長(zhǎng)為(A+B+C)迁沫。所以芦瘾,GC的吞吐量HEAP_SIZE/(A+B+C)。
吞吐量 最大暫停時(shí)間
最大暫停時(shí)間指的是“因執(zhí)行GC而暫停執(zhí)行mutator的最長(zhǎng)時(shí)間”集畅。即上圖中的B近弟。不管嘗試哪種GC算法,都會(huì)發(fā)現(xiàn)較大的吞吐量和較短的最大暫停時(shí)間不可兼得挺智。-
堆使用效率
左右堆使用效率的因素有兩個(gè):
頭的大械挥洹:毋庸置疑,頭越小越好赦颇。因此為了執(zhí)行GC二鳄,需要把在頭中堆放的信息控制在最小限度。
堆的用法:根據(jù)堆的用法媒怯,堆使用效率也會(huì)出現(xiàn)巨大的差異订讼。堆使用效率和吞吐量,以及最大暫停時(shí)間不可兼得扇苞∑鄣睿可用的堆越大,GC運(yùn)行越快鳖敷;相反脖苏,越想有效地利用有限的堆,GC花費(fèi)的時(shí)間就越長(zhǎng)定踱。
-
訪問的局部性
PC上有4種存儲(chǔ)器棍潘,分別是寄存器、緩存、內(nèi)存蜒谤、輔助存儲(chǔ)器山宾。
存儲(chǔ)器一般把所有的數(shù)據(jù)都放在內(nèi)存 里,當(dāng)CPU訪問數(shù)據(jù) 時(shí)鳍徽,僅把要使用的數(shù)據(jù)從內(nèi)存讀取到緩存资锰。與此同時(shí),還將它附近的所有數(shù)據(jù)都讀取到緩存中阶祭,從而壓縮讀取數(shù)據(jù)所需要的時(shí)間绷杜。
具有引用關(guān)系的對(duì)象之間通常很可能存在連續(xù)訪問的情況。這在多數(shù)程序中都很常見濒募,稱為“訪問的局部性”鞭盟。把具有引用關(guān)系的對(duì)象安排在堆中較近的位置,就能提高在緩存中讀取到想利用的數(shù)據(jù)的概率瑰剃,令mutator高速運(yùn)行齿诉。