1. 程式人生 > >Python記憶體與垃圾回收機制

Python記憶體與垃圾回收機制

1、python記憶體管理機制和調優手段。

  記憶體管理機制:引用計數,垃圾回收、記憶體池。

引用計數:

  引用計數是一種非常高效的記憶體管理手段,當一個Python物件被引用時其引用計數增加1,當其不再被一個變數引用時則記數減1,當引用記數等於0時物件被刪除。

垃圾回收:

  1、引用計數:

  引用計數也是一種垃圾收集機制,而且也是一種最直觀,最簡單的垃圾收集技術。當 Python 的某
個物件的引用計數降為 0 時,說明沒有任何引用指向該物件,該物件就成為要被回收的垃圾了。比如
某個新建物件,它被分配給某個引用,物件的引用計數變為 1。如果引用被刪除,物件的引用計數為 0,
那麼該物件就可以被垃圾回收。不過如果出現迴圈引用的話,引用計數機制就不再起有效的作用了 。
  

  2、標記清除

  如果兩個物件的引用計數為1、但是僅僅存在它們兩之間的迴圈引用,那麼這兩個物件都是需要被回收的,也就是說,它們的引用計數雖然表現非0,但實際上有效的引用計數為0,所以先將引用計數摘掉,就會得出這兩個物件的有效計數。

  3、分帶回收

  從前面“標記-清除”這樣的垃圾收集機制來看,這種垃圾收集機制所帶來的額外操作實際上與系統
中總的記憶體塊的數量是相關的,當需要回收的記憶體塊越多時,垃圾檢測帶來的額外操作就越多,而垃圾
回收帶來的額外操作就越少;反之,當需回收的記憶體塊越少時,垃圾檢測就將比垃圾回收帶來更少的額
外操作

舉個例子:

當某些記憶體塊 M 經過了 3 次垃圾收集的清洗之後還存活時,我們就將記憶體塊 M 劃到一個集合
A 中去,而新分配的記憶體都劃分到集合 B 中去。當垃圾收集開始工作時,大多數情況都只對集合 B 進
行垃圾回收,而對集合 A 進行垃圾回收要隔相當長一段時間後才進行,這就使得垃圾收集機制需要處
理的記憶體少了,效率自然就提高了。在這個過程中,集合 B 中的某些記憶體塊由於存活時間長而會被轉
移到集合 A 中,當然,集合 A 中實際上也存在一些垃圾,這些垃圾的回收會因為這種分代的機制而
被延遲。
記憶體池:
1. Python 的記憶體機制呈現金字塔形狀,-1,-2 層主要有作業系統進行操作;
2. 第 0 層是 C 中的 malloc,free 等記憶體分配和釋放函式進行操作;
3. 第 1 層和第 2 層是記憶體池,有 Python 的介面函式 PyMem_Malloc 函式實現,當物件小於
256K 時有該層直接分配記憶體;
4. 第 3 層是最上層,也就是我們對 Python 物件的直接操作;
Python 在執行期間會大量地執行 malloc 和 free 的操作,頻繁地在使用者態和核心態之間進行切
換,這將嚴重影響 Python 的執行效率。為了加速 Python 的執行效率,Python 引入了一個記憶體池
機制,用於管理對小塊記憶體的申請和釋放。
Python 內部預設的小塊記憶體與大塊記憶體的分界點定在 256 個位元組,當申請的記憶體小於 256 位元組
時,PyObject_Malloc 會在記憶體池中申請記憶體;當申請的記憶體大於 256 位元組時,PyObject_Malloc 的
行為將蛻化為 malloc 的行為。當然,通過修改 Python 原始碼,我們可以改變這個預設值,從而改
變 Python 的預設記憶體管理行為。
調優手段(瞭解)
1.手動垃圾回收

2.調高垃圾回收閾值
3.避免迴圈引用(手動解迴圈引用和使用弱引用)