<轉> python的記憶體回收機制

來源:互聯網
上載者:User

標籤:format   記憶體泄露   收集   部落格   idt   ssi   ref   地址   tor   

Python的GC模組主要運用了“引用計數”(reference counting)來跟蹤和回收垃圾。在引用計數的基礎上,還可以通過“標記-清除”(mark and sweep)解決容器物件可能產生的循環參考的問題。通過“分代回收”(generation collection)以空間換取時間來進一步提高記憶體回收的效率。

引用計數機制:    python裡每一個東西都是對象,它們的核心就是一個結構體:PyObject
1 typedef struct_object {2     int ob_refcnt;3     struct_typeobject *ob_type;4 }PyObject;

PyObject是每個對象必有的內容,其中ob_refcnt就是做為引用計數。當一個對象有新的引用時,它的ob_refcnt就會增加,當引用它的對象被刪除,它的ob_refcnt就會減少。

 

1  #define Py_INCREF(op)   ((op)->ob_refcnt++)          //增加計數2  #define Py_DECREF(op)      \                         //減少計數        3       if (--(op)->ob_refcnt != 0)    4           ;        5       else         6           __Py_Dealloc((PyObject *)(op))

 引用計數為0時,該對象生命就結束了。

    引用計數機制的優點:         1、簡單        2、即時性:一旦沒有引用,記憶體就直接釋放了。不用像其他機制等到特定時機。即時性還帶來一個好處:處理回收記憶體的時間分攤到了平時。            引用計數機制的缺點:         1、維護引用計數消耗資源         2、循環參考  
 list1 = [] list2 = [] list1.append(list2) list2.append(list1)
list1與list2相互引用,如果不存在其他對象對它們的引用,list1與list2的引用計數也仍然為1,所佔用的記憶體永遠無法被回收,這將是致命的。    對於如今的強大硬體,缺點1尚可接受,但是循環參考導致記憶體泄露,註定python還將引入新的回收機制。

上面說到python裡回收機制是以引用計數為主,標記-清除和分代收集兩種機製為輔。

 

1、標記-清除機制

標記-清除機制,顧名思義,首先標記對象(垃圾檢測),然後清除垃圾(記憶體回收)。

首先初始所有對象標記為白色,並確定根節點對象(這些對象是不會被刪除),標記它們為黑色(表示對象有效)。將有效對象引用的對象標記為灰色(表示對象可達,但它們所引用的對象還沒檢查),檢查完灰色對象引用的對象後,將灰色標記為黑色。重複直到不存在灰色節點為止。最後白色結點都是需要清除的對象。

2、回收對象的組織

這裡所採用的進階機製作為引用計數的輔助機制,用於解決產生的循環參考問題。而循環參考只會出現在“內部存在可以對其他對象引用的對象”,比如:list,class等。

為了要將這些回收對象組織起來,需要建立一個鏈表。自然,每個被收集的對象內就需要多提供一些資訊,下面代碼是回收對象裡必然出現的。

 

1  /* GC information is stored BEFORE the object structure. */2  typedef union _gc_head {3      struct {4          union _gc_head *gc_next;5          union _gc_head *gc_prev;6          Py_ssize_t gc_refs;7      } gc;8      long double dummy;  /* force worst-case alignment */9  } PyGC_Head;

 

一個對象的實際結構:

通過PyGC_Head的指標將每個回收對象串連起來,形成了一個鏈表,也就是在1裡提到的初始化的所有對象。

 

3、分代回收技術

分代技術是一種典型的以空間換時間的技術,這也正是java裡的關鍵技術。這種思想簡單點說就是:對象存在時間越長,越可能不是垃圾,應該越少去收集。

這樣的思想,可以減少標記-清除機制所帶來的額外操作。分代就是將回收對象分成數個代,每個代就是一個鏈表(集合),代進行標記-清除的時間與代內對象

存活時間成正比例關係

 

 1   /*** Global GC state ***/ 2    3   struct gc_generation { 4       PyGC_Head head; 5       int threshold; /* collection threshold */ 6       int count; /* count of allocations or collections of younger 7                     generations */ 8   };//每個代的結構 9   10  #define NUM_GENERATIONS 3//代的個數11  #define GEN_HEAD(n) (&generations[n].head)12  13  /* linked lists of container objects */14  static struct gc_generation generations[NUM_GENERATIONS] = {15      /* PyGC_Head,                               threshold,      count */16      {{{GEN_HEAD(0), GEN_HEAD(0), 0}},           700,            0},17      {{{GEN_HEAD(1), GEN_HEAD(1), 0}},           10,             0},18      {{{GEN_HEAD(2), GEN_HEAD(2), 0}},           10,             0},19  };20  21  PyGC_Head *_PyGC_generation0 = GEN_HEAD(0);

  

從上面代碼可以看出python裡一共有三代,每個代的threshold值表示該代最多容納對象的個數。預設情況下,當0代超過700,或1,2代超過10,記憶體回收機制將觸發。

0代觸發將清理所有三代,1代觸發會清理1,2代,2代觸發後只會清理自己。

一個完整的記憶體回收流程包括以下四步:鏈表建立,確定根節點,垃圾標記,記憶體回收~  以下部落格進行了很好的闡述:https://my.oschina.net/hebianxizao/blog/59896

 

原文地址:http://www.cnblogs.com/hackerl/p/5901553.html

<轉> python的記憶體回收機制

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.