中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

python垃圾回收機制的示例分析

發布時間:2021-08-03 12:27:29 來源:億速云 閱讀:155 作者:小新 欄目:開發技術

這篇文章主要介紹了python垃圾回收機制的示例分析,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。

  首先還是做一下概述吧: 我們都知道, 在做python的語言編程中, 相較于java, c++, 我們似乎很少去考慮到去做垃圾回收,內存釋放的工作, 其實是python內部已經做了相應的回收機制, 不用我們自己操心去做內存釋放.但是還是有必要了解一下.可以更加深入的了解python這門優美的語言的魅力.

一、概述:

  python的GC模塊主要運用了“引用計數(reference counting)”來跟蹤和回收垃圾。在引用計數的基礎上,還可以通過標記清除(mark and sweep)解決容器(這里的容器值指的不是docker,而是數組,字典,元組這樣的對象)對象可能產生的循環引用的問題。通過“分代回收(generation collection)”以空間換取時間來進一步提高垃圾回收的效率。

二、垃圾回收三種機制

  1、引用計數

  在Python中,大多數對象的生命周期都是通過對象的引用計數來管理的, 廣義上講,它也是一種垃圾回收機制,而且是一種最直觀最簡單的垃圾回收機制。

  原理:當一個對象被創建引用或者被復制的時候,對象的引用計數會加一,當一個對象的引用被銷毀時,對象的引用計數會減一,當對象的引用計數減為0的時候,就意味著對象已經沒有被任何人使用了,可以將其所占用的內存釋放了。

  雖然引用計數必須在每次分配和釋放內存的時候加入管理引用計數的這個動作,然而與其他主流垃圾收集機制相比, 最大的一個優點是實時性, 及任何內存,一旦沒有指向他的引用,就會立即被回收,其他的垃圾回收機制必須在某種特殊條件下(內存分配失敗)才能進行無效內存的回收。

  執行效率問題: 引用計數機制帶來的維護引用計數帶來的額外操作與python運行中所運行的內存分配和釋放,引用賦值的次數是成正比的。相比其他機制,比如“標記-清除”,“停止-復制”,是一個弱點,因為這些技術所帶來的操作基本上只是與待回收的數量有關。

  引用計數還存在的一個致命的弱點是循環引用,這使得垃圾回收機制從來沒有將引用計數包含在內。這就需要我們用新的方法了, 即標記清除。

  2、標記清除

標記清除主要是用來解決循環引用產生的問題的,循環引用只會在容器對象中才會產生,比如數組、字典、元組等,首先是為了追蹤對象,需要每個容器對象維護兩個額外的指針,用來將容器對象組成一個鏈表,指針分別指向前后兩個容器對象,這樣就可以將對象的循環引用環摘除,就可以得出兩個對象的有效計數。

問題說明:

  循環引用可以使得一組對象的引用計數不是0, 然而這些對象實際上并沒有被外部對象所引用,這就意味著不會再有人使用這組對象, 應該回收這組對象所占用的內存空間,然而由于相互引用的存在,每一個對象的引用計數不為0,因為這些對象所占用的內存永遠不會被釋放。比如下面的代碼:

a = [1, 2]
b = [3, 4]
a.append(b)
b.append(a)
del a
del b
# B
c = [3, 5]
d = [2, 4]
c.append(d)
d.append(c)
del c

OKAY,現在就這個做一下解釋,這是個集中營, 一個是root object(鏈表),另一個是unreachable鏈表。

對于上面的第一組, 在未執行del語句的時候,a,b的引用計數都是2(init + append= 2),但是在DEL執行完畢之后,a,b的引用次數互相減一。a,b陷入循環引用的圈子中,然后標記清除算法開始出來做事,找到其中一端a,開始拆a,b的引用環(我們從a出發,因為它對B有一個引用,則將B的引用計數減一,然后順著引用到達B,因為B有一個對A的引用,同樣將A的引用減一,這樣就完成了循環引用對象之間的對象環摘除), 去掉以后發現a,c循環引用變成了0,所以a,b就被處理到unreachable鏈表中直接被做掉。

對于第二組,簡單一看d取環后引用計數還是1,但是a取環后就是0了這時的c已經進入了unreachable的鏈表中,被判了死刑,但是此時在root表中還有d,d還在引用著c,如果c被搞掉,世界就沒有了正義。root鏈表中的d會被引用檢測引用了c,如果c沒了,那么b也就涼涼了,所以c又拉回到了root鏈表中。

解剖這兩個鏈表的原因是現在在unreachable中可能存在被root鏈表中的對象,直接或者間接引用的對象,這些對象是不能被回收的,一旦在標記的過程中,發現這樣的對象就將其移動到root鏈表中,完成標記后,unreachable鏈表中剩下的就是名副其實的垃圾對象了,接下來垃圾回收只需要限制在unreachable鏈表中即可。

  3、分代回收

python垃圾回收機制的示例分析

背景:分代回收技術是上個世紀80年代初發展起來的一種垃圾回收機制,經過研究表明:無論使用何總語言開發無論開發的是何種類型,何種規模的程序,都存在這樣一點相同之處, 即:一定比例的內存塊的生存周期都比較短,通常是幾百萬條指令的時間,然而剩下的內存塊,生存周期比較長,甚至會從一開始直到程序結束。

從前面的“標記-清除”這樣的垃圾回收機制來看,這種垃圾收集機制帶來的額外操作實際上與系統中總的內存塊的數量是相關的,當要回收的內存塊越多時,垃圾檢測帶來的額外操作就越多,而垃圾回收所帶來的額外操作就越少,反值則相反。為了提高垃圾的收集效率,采用“空間換時間”的策略。

原理: 將系統紅所有內存塊根據其存活時間劃分為不同的集合每一個集合就稱為一個“代”,垃圾收集的頻率隨著代的存活時間的增大而減少。也即,活的時間越長的對象就越不可能是垃圾,就應該減少對它的垃圾收集頻率,衡量的標準就是這個對象經過的垃圾收集次數越多,該對象存活的時間就越長。

例如:

  當某些內存塊M經過了3次垃圾回收的清洗之后還是存活著的時候,就將內存塊M劃到一個集合A中去,當垃圾收集開始工作時,大多數情況只是針對集合B進行垃圾回收,而對集合A進行垃圾回收要隔相當長一段時間才進行,這就使得垃圾收集機制要處理的內存少了,效率自然就提高了。這個過程中集合B中的某些內存塊由于存活時間長會被轉移到A中, 當然A中實際上也存在一些垃圾,這些垃圾回收會因為這種分帶機制而延遲。 在python中,一共有三代,也即維護3條鏈表(generation 0, 1, 2)

  • 0代表幼兒對象。

  • 1代表青年對象。

  • 2代表老年對象。

依據弱代假說(越年輕的越容易死掉)

新生的對象放在0代,對象在0代的第一次垃圾收集機制中活了過來, 那么久將其放到第1代里面了,同理,可能會被放到第2代。GC每代垃圾回收處罰的閾值可以自己設置(目前我不知道怎么設置/苦笑)。

這些就是目前的python的垃圾回收機制了。

下面的是 內存池以及調優手段:

內存池:

python的內存機制呈現金字塔形狀,-1, -2層主要由操作系統進行操作。

第0層是C中的malloc, free等內存分配和釋放函數進行操作

第一層和第二層是內存池,有python借口函數,PyMem_Malloc函數實現,當對象小于256K時候由該層直接分配內存,

第三層是最上層,也即我們對python對象的直接操作。

調優手段:

1、手動垃圾回收

2、避免循環運用

3、提高垃圾回收閾值

感謝你能夠認真閱讀完這篇文章,希望小編分享的“python垃圾回收機制的示例分析”這篇文章對大家有幫助,同時也希望大家多多支持億速云,關注億速云行業資訊頻道,更多相關知識等著你來學習!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

SHOW| 临洮县| 织金县| 杭锦旗| 吉林省| 房产| 宣汉县| 中方县| 乌兰察布市| 镇平县| 松阳县| 东兰县| 阳泉市| 天台县| 上林县| 志丹县| 搜索| 安乡县| 白河县| 宁强县| 呼图壁县| 方正县| 本溪市| 三河市| 陈巴尔虎旗| 横峰县| 泉州市| 安新县| 循化| 莎车县| 玉龙| 奉节县| 五河县| 安泽县| 会理县| 灵璧县| 山丹县| 池州市| 德江县| 太仓市| 中山市|