gc

 

垃圾回收
1. 小整數對象池
整數在程序中的使用很是普遍,Python爲了優化速度,使用了小整數對象池,避免爲整數頻繁申請和銷燬內存空間。python

Python 對小整數的定義是 [-5, 257) 這些整數對象是提早創建好的,不會被垃圾回收。在一個Python 的程序中,全部位於這個範圍內的整數使用的都是同一個對象.函數

同理,單個字母也是這樣的。優化

可是當定義2個相同的字符串時,引用計數爲0,觸發垃圾回收spa

2. 大整數對象池
每個大整數,均建立一個新的對象。debug

In [29]: id(b)
Out[29]: 10914368

In [30]: a=1000

In [31]: b=1000

In [32]: id(a)
Out[32]: 139681389577584

In [33]: id(b)
Out[33]: 139681389577712

  

3. intern機制日誌

a1 = "HelloWorld"
a2 = "HelloWorld"
a3 = "HelloWorld"
a4 = "HelloWorld"
a5 = "HelloWorld"
a6 = "HelloWorld"
a7 = "HelloWorld"
a8 = "HelloWorld"
a9 = "HelloWorld"

python會不會建立9個對象呢?在內存中會不會開闢9個」HelloWorld」的內存空間呢? 想一下,若是是這樣的話,咱們寫10000個對象,好比a1=」HelloWorld」…..a1000=」HelloWorld」, 那他豈不是開闢了1000個」HelloWorld」所佔的內存空間了呢?若是真這樣,內存不就爆了嗎?因此python中有這樣一個機制——intern機制,讓他只佔用一個」HelloWorld」所佔的內存空間。靠引用計數去維護什麼時候釋放。code

 

總結
小整數[-5,257)共用對象,常駐內存
單個字符共用對象,常駐內存
單個單詞,不可修改,默認開啓intern機制,共用對象,引用計數爲0,則銷燬 單詞垃圾回收
字符串(含有空格),不可修改,沒開啓intern機制,不共用對象,引用計數爲0,銷燬
大整數不共用內存,引用計數爲0,銷燬 大整數垃圾回收
數值類型和字符串類型在 Python 中都是不可變的,這意味着你沒法修改這個對象的值,每次對變量的修改,其實是建立一個新的對象不可變對象

 

循環引用而且關閉gc,內存不斷增長blog

import gc

class Test1(object):
    def __init__(self):
        print("object born,id:%s"%str(hex(id(self))))

def f2():
    while True:
        c1 = Test1()
        c2 = Test1()
        c1.t = c2
        c2.t = c1
        del c1
        del c2
gc.disable()
f2()

  

 

python採用的是引用計數爲主,隔代回收爲輔的垃圾回收策略接口

GC系統承擔的工做遠比「垃圾回收」多得多。

主要負責三個任務:

一、爲新生成的對象分配內存

二、識別那些垃圾對象

三、從垃圾對象那回收內存

 

分代回收思想將對象分爲三代(generation 0,1,2),0表明幼年對象,1表明青年對象,2表明老年對象。根據弱代假說(越年輕的對象越容易死掉,老的對象一般會存活更久。)
新生的對象被放入0代,若是該對象在第0代的一次gc垃圾回收中活了下來,那麼它就被放到第1代裏面(它就升級了)。若是第1代裏面的對象在第1代的一次gc垃圾回收中活了下來,它就被放到第2代裏面。gc.set_threshold(threshold0[,threshold1[,threshold2]])設置gc每一代垃圾回收所觸發的閾值。從上一次第0代gc後,若是分配對象的個數減去釋放對象的個數大於threshold0,那麼就會對第0代中的對象進行gc垃圾回收檢查。 從上一次第1代gc後,若是第0代被gc垃圾回收的次數大於threshold1,那麼就會對第1代中的對象進行gc垃圾回收檢查。一樣,從上一次第2代gc後,如過第1代被gc垃圾回收的次數大於threshold2,那麼就會對第2代中的對象進行gc垃圾回收檢查。

 

gc模塊經常使用功能

gc模塊提供一個接口給開發者設置垃圾回收的選項。上面說到,採用引用計數的方法管理內存的一個缺陷是循環引用,而gc模塊的一個主要功能就是解決循環引用的問題。

###經常使用函數
一、gc.set_debug(flags)設置gc的debug日誌,通常設置爲gc.DEBUG_LEAK

二、gc.collect([generation]) 顯式進行垃圾回收,能夠輸入參數,0表明只檢查第一代的對象,1表明檢查一,二代的對象,2表明檢查一,二,三代的對象,若是不傳參數,執行一個full collection,也就是等於傳2。 返回不可達(unreachable objects)對象的數目

三、gc.get_threshold() 獲取的gc模塊中自動執行垃圾回收的頻率。

四、gc.set_threshold(threshold0[, threshold1[, threshold2]) 設置自動執行垃圾回收的頻率。

五、gc.get_count() 獲取當前自動執行垃圾回收的計數器,返回一個長度爲3的列表

 

查看當前分代回收的頻率

In [9]: gc.get_threshold()
Out[9]: (700, 10, 10)

  

 

一、致使引用計數+1的狀況:
對象被建立,例如a=23
對象被引用,例如b=a
對象被做爲參數,傳入到一個函數中,例如func(a)
對象做爲一個元素,存儲在容器中,例如list=[a,a]


二、致使引用計數-1的狀況:
對象的別名被顯示銷燬,例如del a
對象的別名被賦予新的對象,例如a=24
一個對象離開它的做用域,例如f函數執行完畢時,func函數中的局部變量(全局變量不會改變)
對象所在的容器被銷燬,或從容器中刪除對象

 

 三、查看一個對象的引用計數

In [9]: a = "hello world"

In [10]: sys.getrefcount(a)
Out[10]: 2
相關文章
相關標籤/搜索