【转】.net框架读书笔记---CLR内存管理\垃圾收集(六)
對象代齡
代齡是旨在提高垃圾收集器性能的一種機制。有以下幾點:
在托管堆初始化時,其中不包含任何對象。這時添加到托管堆中的對象被稱為第0代對象。第0代對象就是新構造的對象,垃圾收集器還沒有對他們執行過任何的檢查,加入新啟動一個應用程序托管堆,分配了5個對象(A到E),經過一段時間后,對象C和E將變為不可達對象。
當CLR初始化時,它會為第0代對象選擇一個閾值,假定為256KB。(實際可能會與此不同)當分配新對象導致第0代對象超過了為其設定的闕值時,垃圾收集器就必須啟動了。假定上面的A到E總共占用了256KB,那么當F開始被分配時,垃圾收集器就會啟。垃圾收集器判定對象C和E為垃圾,因此會壓縮對象D使其鄰接于對象B。此次垃圾收集器中存活下來的對象(對象A,B,D)將被認為是第1代對象。經過一輪垃圾收集的檢查加強的存活下來并且光榮的升官加爵。
在第一次垃圾收集執行后,0代對象暫時空缺。但很快,隨著應用程序的運行,又有新的對象被分配而成為第0代對象。新加入的F到K就變為了0代對象變為了準炮灰。隨著應用程序的運行,對象B(一代長老),H(0)和J(0)又成為不可達對象,它們的內存也要在某一點被回收。
現在假設應用程序又試圖分配對象L,這將在一次使第0代對象超過它的闕值容量,于是又必須開始執行第二次垃圾收集。在這前面,垃圾收集器必須要判定要收集那些代的對象。垃圾收集器期會為0代對象選擇一個闕值(大約256KB),其實也會為第1代對象選擇一個闕值容量。假設第1代對象的闕值容量為2MB。
當第二次垃圾收開始執行時,它也會查看第1代對象占用了多少內存,在本例中,由于第一代對象(A,B,D)占用內存遠少于2MB,所以垃圾收集器只會去檢查第0代對象。由于新創建的對象的生存期比較短,所以第0代對象成為垃圾對象的數量會比較多,因此對第0代對象執行垃圾收集將有可能比較多的內存,忽略掉第1代對象提高垃圾收集的速度。
忽略第1代對象的意義不僅僅在于不對它們執行垃圾收集。實際上,更重要的是垃圾收集器不用再遍歷整個托管堆中的對象了,可以提高垃圾收集器的性能。說忽略代齡較大的對象的一些內部引用,而不是全部內部引用是因為代齡較大的對象有可能引用一個新的對象。為了確保這些代齡較大的對象中的一些新對象也能被檢測到,垃圾收集器使用JIT編譯器內部的一種機制來在對象的內部引用字段改變時設置一個相應的為標記。這使得垃圾收集器可以知道自從上次垃圾收集執行后以來,那些代齡較大的對象已經被應用程序所改寫。這樣垃圾收集器只需檢查它們是否引用了第0代對象就可以了。
生存期比較長的對象將趨向于繼續存活,所以第一代對象繼續成為可達對象的可能性比較大。所以第一代對象繼續成為可達對象的可能性比較大。因此垃圾收集器檢查第一代對象,很有可能找不到很多垃圾,能夠回收的內存也就有限,這樣收集第一代很有可能浪費大量的時間。如果垃圾對象位于第一代,那么它仍然健在。第二次垃圾收集后。托管堆中存在
A--B---D---F--G---I---K(均為一代長老了)
第0代對象中的幸存者有升官加爵了變為1代,因為垃圾收集器沒有檢查第一代,B內存沒有被收集。雖然已經成為不可達對象。但是由于沒有經歷洗禮,所以沒有升官加爵;
此時0代為空,新的對象繼續加入成為了0代長老(L到O),過一段時間,G、L、M又成為不可達對象。此時托管堆如下:
一代A---B---D---F---G---I---K 0代L---M---N---O
此時1代中堆著N多的不可達垃圾包括B。
此時對象P的加入又是0代超標了,繼續垃圾收集。因為1代的容量2MB,沒有超標,繼續不對1代收集(B,G為1代中的蛀蟲);本次垃圾收集完畢后,托管堆如下:
一代A---B---D---F---G---I---K---N----O
0代被適時殺死,一代里面的蛀蟲繼續增長,沒有控制是不行的,結果一代的容量達到了其闕值2MB,此時應用程序分配P到S對象,這時0代又滿了。此時托管堆的分配情況:
一代A---B---D---F---G---I---K---N----O? 0代P----Q----R----S
此時應用程序試圖分配對象T,當然是沒有地方了,0,1代都滿了,需要清理了,這時發現一代對象的內存容量已經達到了2MB,然而一代中存在著大量幸存下來的垃圾。本次垃圾收集器是公平的,同時收集第0代和第1代中所有的垃圾對象,痛苦,所以的垃圾一掃而光了,此時托管堆為:
二代D---F---I----N----O? 二代Q-----S(0代空了)
和前面一樣,本次垃圾收集完畢后,幸存下來的將被提升為1代,而一代中存活下來的被榮升為2代了,0代為空了,在產生第二代對象之前,系統有可能已經執行了多次垃圾收集,但只有在第一代對象的內存總量達到其闕值時,垃圾收集器才會檢查一代對象,而此時系統可能已經對0代對象執行了N多次垃圾收集了。
CLR托管堆只支持3個代齡,0,1,2,CLR初始化時都會為其設置闕值容量(大約為,256KB,2MB,10MB),
CLR垃圾收集器是一個自調結的玩意,他會根據對象的狀態,變為不可達的頻率自適應的調節闕值。實在是高啊。
?
CLR的垃圾收集原理其實也給人一人生道理,要想活得更長,就需向更高一層走,而要想往更高一層走就要經過殘酷的洗禮。剩者為王。
?
- 屠刀總是先指向弱者,因為強者數大根深啊,殺一次得不償失
- 強者擁有更多的資源和更多的容忍
- 再強也不要超過別人給的限度,否則權利是人家給的,人家不高興了隨時可以拿回去
總結
以上是生活随笔為你收集整理的【转】.net框架读书笔记---CLR内存管理\垃圾收集(六)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 学历低不能办理信用卡吗
- 下一篇: 画面补丁翻车严重:《生化危机》多部作品遭