如何快速理解python的垃圾回收機(jī)制
一、先來(lái)說(shuō)說(shuō)為什么要有垃圾回收
解釋器在執(zhí)行到定義變量得語(yǔ)法時(shí),會(huì)申請(qǐng)內(nèi)存空間來(lái)存放變量得值,但是由于內(nèi)存空間是有限得,所以這就涉及到了內(nèi)存回收問(wèn)題了,當(dāng)一個(gè)變量值沒(méi)有用了(簡(jiǎn)稱垃圾),這種時(shí)候就應(yīng)該回收掉這個(gè)變量值得內(nèi)存空間。
二、那么什么是垃圾回收機(jī)制
垃圾回收機(jī)制(簡(jiǎn)稱GC)是Python解釋器自帶一種機(jī),專門用來(lái)回收不可用的變量值所占用的內(nèi)存空間
三、為什么要用垃圾回收機(jī)制呢?
程序運(yùn)行過(guò)程中會(huì)申請(qǐng)大量的內(nèi)存空間,而對(duì)于一些無(wú)用的內(nèi)存空間如果不及時(shí)清理的話會(huì)導(dǎo)致內(nèi)存使用殆盡(內(nèi)存溢出),導(dǎo)致程序崩潰,因此管理內(nèi)存是一件重要且繁雜的事情,而python解釋器自帶的垃圾回收機(jī)制把程序員從繁雜的內(nèi)存管理中解放出來(lái)。
四、垃圾回收機(jī)制的理解
1、堆區(qū)和棧區(qū)
在定義變量時(shí),變量名與變量值都是需要存儲(chǔ)的,分別對(duì)應(yīng)內(nèi)存中的兩塊區(qū)域:堆區(qū)與棧區(qū)。
# 1、變量名與值內(nèi)存地址的關(guān)聯(lián)關(guān)系存放于棧區(qū) # 2、變量值存放于堆區(qū),內(nèi)存管理回收的則是堆區(qū)的內(nèi)容
2、直接引用和間接引用
直接引用指的是從棧區(qū)出發(fā)直接引用到的內(nèi)存地址。間接引用指的是從棧區(qū)出發(fā)引用到堆區(qū)后,再通過(guò)進(jìn)一步引用才能到達(dá)的內(nèi)存地址。
x=10 # 10這個(gè)值被變量x直接引用 list=[20,x] # 10這個(gè)值被列表list間接引用12
五、垃圾回收機(jī)制的原理分析
Python的GC模塊主要運(yùn)用了“引用計(jì)數(shù)”(reference counting)來(lái)跟蹤和回收垃圾。在引用計(jì)數(shù)的基礎(chǔ)上,還可以通過(guò)“標(biāo)記-清除”(mark and sweep)解決容器對(duì)象可能產(chǎn)生的循環(huán)引用的問(wèn)題,并且通過(guò)“分代回收”(generation collection)以空間換取時(shí)間的方式來(lái)進(jìn)一步提高垃圾回收的效率。
1、引用計(jì)數(shù)
變量值被變量名關(guān)聯(lián)得次數(shù)(包括間接引用和直接引用 ),一旦變量得引用計(jì)數(shù)得值變成0,占用內(nèi)存就會(huì)被回收。
2、引用計(jì)數(shù)得問(wèn)題以及解決方案
問(wèn)題一:循環(huán)引用
引用計(jì)數(shù)機(jī)制存在著一個(gè)致命的弱點(diǎn),即循環(huán)引用(也稱交叉引用
list1=[111,] list2=[222,] list1.append(list2) list2.append(list1) print(list1,list2) [111, [222, [...]]] [222, [111, [...]]] # list1和list2之間相互引用 # list1=[111的內(nèi)存地址,list2的內(nèi)存地址] # list2=[222的內(nèi)存地址,list1的內(nèi)存地址] x=10 list=[2,3,x] print(list[2]) # 10 x=123 print(list[2]) # 10
這種時(shí)候一旦我們del list1,del list2,刪除列表的直接引用,只剩下list1和list2之間 的相互引用,這樣引用計(jì)數(shù)不是0,內(nèi)存空間無(wú)法回收,并且無(wú)法去到list1和list2的值(就是垃圾),這種時(shí)候python引入了“標(biāo)記-清除” 與“分代回收”來(lái)分別解決引用計(jì)數(shù)的循環(huán)引用與效率低的問(wèn)題。
問(wèn)題二:標(biāo)記清除
容器對(duì)象(比如:list,set,dict,class,instance)都可以包含對(duì)其他對(duì)象的引用,所以都可能產(chǎn)生循環(huán)引用。而“標(biāo)記-清除”計(jì)數(shù)就是為了解決循環(huán)引用的問(wèn)題。標(biāo)記/清除算法的做法是當(dāng)應(yīng)用程序可用的內(nèi)存空間被耗盡的時(shí),就會(huì)停止整個(gè)程序,然后進(jìn)行兩項(xiàng)工作,第一項(xiàng)則是標(biāo)記,第二項(xiàng)則是清除。
問(wèn)題三:效率問(wèn)題
基于引用計(jì)數(shù)的回收機(jī)制,每次回收內(nèi)存,都需要把所有對(duì)象的引用計(jì)數(shù)都遍歷一遍,這是非常消耗時(shí)間的,于是引入了分代回收來(lái)提高回收效率,分代回收采用的是用“空間換時(shí)間”的策略。
問(wèn)題四:分代回收
分代回收的核心思想是:在歷經(jīng)多次掃描的情況下,都沒(méi)有被回收的變量,gc機(jī)制就會(huì)認(rèn)為,該變量是常用變量,gc對(duì)其掃描的頻率會(huì)降低分代指的是根據(jù)存活時(shí)間來(lái)為變量劃分不同等級(jí)(也就是不同的代)
新定義的變量,放到新生代這個(gè)等級(jí)中,假設(shè)每隔1分鐘掃描新生代一次,如果發(fā)現(xiàn)變量依然被引用,那么該對(duì)象的權(quán)重(權(quán)重本質(zhì)就是個(gè)整數(shù))加一,當(dāng)變量的權(quán)重大于某個(gè)設(shè)定得值(假設(shè)為3),會(huì)將它移動(dòng)到更高一級(jí)的青春代,青春代的gc掃描的頻率低于新生代(掃描時(shí)間間隔更長(zhǎng)),假設(shè)5分鐘掃描青春代一次,這樣每次gc需要掃描的變量的總個(gè)數(shù)就變少了,節(jié)省了掃描的總時(shí)間,接下來(lái),青春代中的對(duì)象,也會(huì)以同樣的方式被移動(dòng)到老年代中。也就是等級(jí)(代)越高,被垃圾回收機(jī)制掃描的頻率越低
回收依然使用引用計(jì)數(shù)作為回收的依據(jù)
問(wèn)題五:分代回收的缺點(diǎn)
例如一個(gè)變量剛剛從新生代移入青春代,該變量的綁定關(guān)系就解除了,該變量應(yīng)該被回收,但青春代的掃描頻率低于新生代,這就到導(dǎo)致了應(yīng)該被回收的垃圾沒(méi)有得到及時(shí)地清理。
沒(méi)有十全十美的方案:
毫無(wú)疑問(wèn),如果沒(méi)有分代回收,即引用計(jì)數(shù)機(jī)制一直不停地對(duì)所有變量進(jìn)行全體掃描,可以更及時(shí)地清理掉垃圾占用的內(nèi)存,但這種一直不停地對(duì)所有變量進(jìn)行全體掃描的方式效率極低,所以我們只能將二者中和。
綜上:
垃圾回收機(jī)制是在清理垃圾&釋放內(nèi)存的大背景下,允許分代回收以極小部分垃圾不會(huì)被及時(shí)釋放為代價(jià),以此換取引用計(jì)數(shù)整體掃描頻率的降低,從而提升其性能,這是一種以空間換時(shí)間的解決方案目錄。
以上就是如何快速理解python的垃圾回收機(jī)制的詳細(xì)內(nèi)容,更多關(guān)于你理解python的垃圾回收機(jī)制么的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
使用python搭建服務(wù)器并實(shí)現(xiàn)Android端與之通信的方法
今天小編就為大家分享一篇使用python搭建服務(wù)器并實(shí)現(xiàn)Android端與之通信的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-06-06Python分析特征數(shù)據(jù)類別與預(yù)處理方法速學(xué)
這篇文章主要為大家介紹了Python分析特征數(shù)據(jù)類別與預(yù)處理方法速學(xué),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-02-02你喜歡籃球嗎?Python實(shí)現(xiàn)籃球游戲
今天帶大家學(xué)習(xí)的是關(guān)于Python的相關(guān)知識(shí),文章圍繞著Python如何實(shí)現(xiàn)籃球游戲展開(kāi),文中有非常詳細(xì)的介紹及代碼示例,需要的朋友可以參考下2021-06-06Python pathlib模塊使用方法及實(shí)例解析
這篇文章主要介紹了Python pathlib模塊使用方法及實(shí)例解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-10-10Python??序列化反序列化和異常處理的問(wèn)題小結(jié)
這篇文章主要介紹了Python?序列化反序列化和異常處理,本文結(jié)合示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-12-12Python 多繼承中的一個(gè)詭異現(xiàn)象 既是 Father又是grandfather
我們知道,在面向?qū)ο缶幊汤锩?,繼承是一個(gè)很重要的概念。子類可以使用父類的方法和屬性,接下來(lái)小編將用舉例的方式為大家講解Python 多繼承中的一個(gè)詭異現(xiàn)象 其即是爸爸又是爺爺?shù)钠孑猬F(xiàn)象,感興趣的小伙伴可以看下面文章具體了解2021-09-09NumPy隨機(jī)數(shù)據(jù)分布與Seaborn可視化詳解
數(shù)據(jù)分布是指數(shù)據(jù)集中所有可能值出現(xiàn)的頻率,并用概率來(lái)表示,它描述了數(shù)據(jù)取值的可能性,Seaborn 是一個(gè)基于 Matplotlib 的 Python 數(shù)據(jù)可視化庫(kù),用于創(chuàng)建統(tǒng)計(jì)圖表,本文就給大家詳細(xì)的介紹一下NumPy隨機(jī)數(shù)據(jù)分布與Seaborn可視化,需要的朋友可以參考下2024-05-05