對比Ruby和Python的垃圾回收
當然Python內部也會由于各種原因使用空閑對象鏈表(它使用鏈表循環(huán)確定對象),Python為對象和值分配內存的方式常常不同于Ruby。
本文引用地址:http://m.butianyuan.cn/article/201609/304199.htm假設我們創(chuàng)建一個Node對象使用Python:
![pythobvdfbfdbdfbn1](http://editerupload.eepw.com.cn/fetch/20160912/304199_2_0.jpg)
Python不同于Ruby,當你創(chuàng)建對象的時候,Python會立即向操作系統(tǒng)申請分配內存。(Python 事實上實現了自己的內存分配系統(tǒng),它在操作系統(tǒng)內存堆上提供了另外一層抽象,但是今天沒有事件深入探討。 )
當我們創(chuàng)建第二個對象時,Python將再次向操作系統(tǒng)申請更多的內存:
![python2fbfdhhrt](http://editerupload.eepw.com.cn/fetch/20160912/304199_2_1.jpg)
看起來相當簡單,當我們創(chuàng)建Python對象的時刻,將花費事件申請內存。
![menbfgnfgnfhss](http://editerupload.eepw.com.cn/fetch/20160912/304199_2_2.jpg)
Ruby開發(fā)者生活在一個臟亂的房間
回到Ruby,由于我們分配越來越多的對象,Ruby將繼續(xù)為我們從空閑對象鏈表(free list)獲取預分配對象。因此,空閑對象鏈表將變得越來越短:
![fregergregrgge-list4](http://editerupload.eepw.com.cn/fetch/20160912/304199_2_3.jpg)
或者更短:
![freederfreferfg-list5](http://editerupload.eepw.com.cn/fetch/20160912/304199_2_4.jpg)
請注意,我將一個新的值賦給了n1,Ruby會遺留下舊的值。”ABC”, “JKL”和”MNO”等結點對象會依然保留在內存中。Ruby不會立即清理舊的對象盡管程序不再使用!作為一名Ruby開發(fā)者就像生活在一個臟亂的房間,衣服隨意的仍在地板上,廚房的水槽中堆滿了臟盤子。作為一個Ruby開發(fā)者,你必須在一大堆垃圾對象中去工作。
![clfgdgergerggrean](http://editerupload.eepw.com.cn/fetch/20160912/304199_2_5.jpg)
當你的程序不在使用任何對象的時候,Python會立刻進行清理。
Python開發(fā)者生活在一所整潔的房子
垃圾回收機制在Python和Ruby中迥然不同,讓我們回到前面三個Python中Node對象的例子:
![pythfgbfgbfgbnfgon3b](http://editerupload.eepw.com.cn/fetch/20160912/304199_2_6.jpg)
內部的,每當我們新建一個對象,Python將在對象對應的C語言結構中保存一個數字,叫做引用技術。最初,Python將它的值設為1。
![pytefwefwefwefghon4](http://editerupload.eepw.com.cn/fetch/20160912/304199_2_7.jpg)
值為1表明每個對象有一個指針或引用指向它。假設我們創(chuàng)建一個新的對象,JKL:
![pythgbfgbfbfgbon5](http://editerupload.eepw.com.cn/fetch/20160912/304199_2_8.jpg)
正如前面所說,Python將”JKL”的引用計數設置為1。同樣注意到我們改變n1指向了”JKL”,不再引用”ABC”,同時將”ABC”的引用計數減少為0。
通過這一點,Python垃圾回收器將會立即執(zhí)行!無論何時,只要一個對象的引用計數變?yōu)?,python將立即釋放這個對象,并且將它的內存返回給操作系統(tǒng)。
![pythgfbfgbfgnbfgnon6](http://editerupload.eepw.com.cn/fetch/20160912/304199_2_9.jpg)
上圖中,Python將回收”ABC”對象的內存。記住,Ruby只是將舊的對象遺留在那里并且不去釋放它們占用的內存。
這種垃圾回收算法被稱為”引用計數”,由喬治柯林斯發(fā)明于1960年。非常巧合的是在同一年約翰麥卡錫大叔發(fā)明了”空閑對象鏈表算法”。正如Mike Bernstein在Ruby Conference大會上所說”1960年是屬于垃圾回收器的…”。
作為一個Python開發(fā)者,就像生活在一個整潔的房間中。你知道,你的室友有些潔癖,他會把你使用過的任何東西都清洗一遍。你把臟盤子,臟杯子一放到水槽中他就會清洗。
現在看另外一個例子,假設我們讓n2和n1指向同樣的結點:
![pytvwefwefwefhon8](http://editerupload.eepw.com.cn/fetch/20160912/304199_2_10.jpg)
上圖左邊可以看到,Python減少了”DEF”的引用計數并且立即回收了”DEF”對象。同時可以看到,由于n1和n2同時指了”JKL”對象,所以它的引用計數變?yōu)榱?。
標記回收算法
最終臟亂的房間將堆慢垃圾,生活不能總是如此。Ruby程序在運行一段時間之后,空閑對象鏈表最終將被用盡。
![mark-fthrthand-sweep1](http://editerupload.eepw.com.cn/fetch/20160912/304199_2_11.jpg)
上圖中所有的預分配對象都被用盡(方塊全部變成了灰色),鏈表上沒有對象可用(沒有剩余的白色方塊)。
此時,Ruby使用了一種由約翰麥卡錫發(fā)明的被稱為”標記回收”的算法。首先,Ruby將停止程序的執(zhí)行,Ruby使用了”停止這個世界,然后回收垃圾”的方式。然后,Ruby會掃描所有的指向對象和值的指針或引用。同樣,Ruby也會迭代虛擬機內部使用的指針。它會標記每一個指針所能到達的對象。在下圖中,我使用了”M”指出了這些標記:
評論