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