1. 程式人生 > >Python之記憶體管理機制

Python之記憶體管理機制

Python使用gc模組處理python物件以及python垃圾回收器的工作,完整的gc模組文件參考這裡。舉gc模組的幾個例子看一下:

  • gc.enable()——可自動進行垃圾回收;
  • gc.disable()——不可自動進行垃圾回收;
  • gc.set_threshold()——設定python垃圾回收的閾值;
  • gc.set_debug()——設定垃圾回收的除錯標記,除錯資訊會被寫入std.err;
  • gc.get_objects()——返回收集器跟蹤的所有物件的列表,不包括返回的列表。
  • ......

Python的記憶體管理機制主要包括三個方面:引用計數機制、垃圾回收機制、記憶體池機制

一、引用計數機制

Python內部使用引用計數來保持追蹤記憶體中的物件,所有物件都有引用計數。

引用計數增加的情況:

(1)物件被建立:x=1;

(2)被物件已有引用賦值:y=x;

(3)被作為引數傳遞給函式:f(x);

(4)將其放入一個人容器中,如列表、元組或字典。

引用計數減少的情況:

(1)一個本地引用離開了它的作用域。比如上面的f(x)函式結束時,x指向的物件引用就會減1;

(2)使用del語句對物件別名顯式的銷燬:del x;

(3)引用被重新賦值:x=2;

(4)物件從一個視窗物件中移除:myList.remove(x);

(5)視窗物件本身被銷燬:del myList,或視窗物件本身離開了作用域:f(myList)

使用sys.getrefcount()函式可以獲得物件的當前引用計數。大多數情況下,引用計數比你猜測得要大得多。

對於不可變資料(如數字和字串),直譯器會在程式的不同部分共享記憶體,以便節約記憶體。

二、垃圾回收

(1)引用計數

引用計數也是一種垃圾收集機制,而且是一種最直觀、最簡單的垃圾收集技術。黨某個物件的引用計數降為0時,說明沒有任何引用指向該物件,該物件就成為要回收的垃圾,被回收掉。但是有一個例外,迴圈引用是物件之間的相互引用,會使得一組物件的引用計數不為0,然後這些物件實際上沒有被任何外部物件所引用,這些物件就會佔記憶體永遠不會被釋放掉。

因此Python又引入了其他的垃圾回收機制來彌補引用計數的缺陷:“標記-清理”,“分代回收”。

(2)標記清理

對於迴圈引用,當兩個物件相互引用時,del語句可以減少a和b的引用計數,並銷燬用於引用底層物件的名稱。然而由於每個物件都包含對其他物件的引用,因此引用計數不會歸零,物件也不會銷燬;從而導致記憶體洩漏。為了解決這一問題,直譯器會定期執行一個迴圈檢測器,搜尋不可訪問的物件的迴圈並刪除它們。

在實際操作中並不改動真實的引用計數,而是將集合中物件的引用計數複製一份副本,改動該物件引用的副本。(對於副本做任何的改動,都不會影響到物件生命週期的維護。)這個計數副本的唯一作用是尋找root object集合(該集合中的物件是不能被回收的)。當成功尋找到root object集合之後,首先將現在的記憶體連結串列一分為二,一條連結串列中維護root object集合,成為root連結串列,而另外一條連結串列中維護剩下的物件,成為unreachable連結串列。之所以要剖成兩個連結串列,是基於這樣的一種考慮:現在的unreachable可能存在被root連結串列中的物件直接或間接引用的物件,這些物件是不能被回收的,一旦在標記的過程中,發現這樣的物件,就將其從unreachable連結串列中移到root連結串列中;當完成標記後,unreachable連結串列中剩下的所有物件就是名副其實的垃圾物件了,接下來的垃圾回收只需限制在unreachable連結串列中即可。

(3)分代回收

從前面“標記-清除”這樣的垃圾收集機制來看,這種垃圾收集機制所帶來的額外操作實際上與系統中總的記憶體塊的數量是相關的,當需要回收的記憶體塊越多時,垃圾檢測帶來的額外操作就越多,而垃圾回收帶來的額外操作就越少;反之,當需回收的記憶體塊越少時,垃圾檢測就將比垃圾回收帶來更少的額外操作。
舉個例子來說明:
當某些記憶體塊M經過了3次垃圾收集的清洗之後還存活時,我們就將記憶體塊M劃到一個集合A中去,而新分配的記憶體都劃分到集合B中去。當垃圾收集開始工作時,大多數情況都只對集合B進行垃圾回收,而對集合A進行垃圾回收要隔相當長一段時間後才進行,這就使得垃圾收集機制需要處理的記憶體少了,效率自然就提高了。在這個過程中,集合B中的某些記憶體塊由於存活時間長而會被轉移到集合A中,當然,集合A中實際上也存在一些垃圾,這些垃圾的回收會因為這種分代的機制而被延遲。

三、記憶體池機制

Python提供了對記憶體的垃圾收集機制,但是它是將不用的記憶體放到記憶體池,而不是返回給系統。

python中記憶體機制呈現出金字塔形狀,-1、-2層主要由作業系統進行操作。第0層是c中的malloc,free等記憶體分配和釋放函式進行操作。

(1)第1層和第2層是記憶體池,有Python的介面函式PyMem_Malloc函式實現。Python 中所有小於256個位元組的物件都使用pymalloc實現的分配器,而大的物件則使用系統的malloc。不過,通過修改Python原始碼,我們可以改變這個預設值,從而改變Python的預設記憶體管理行為。

Python引入了一個記憶體池機制,是為了加速Python的執行效率,用於管理對小塊記憶體的申請和釋放。

(3)對於python物件,如整數、浮點數、List,都有其獨立的私有記憶體池,物件間不共享它們的記憶體池。也就是說,如果你分配又釋放了大量的整數,用於快取這些整數的記憶體就不能再分配給浮點數。(值語義)


圖片來源:http://blog.csdn.net/alertbear/article/details/50808178

相關推薦

Python記憶體管理機制

Python使用gc模組處理python物件以及python垃圾回收器的工作,完整的gc模組文件參考這裡。舉gc模組的幾個例子看一下: gc.enable()——可自動進行垃圾回收;gc.disable()——不可自動進行垃圾回收;gc.set_threshold()——

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

python的記憶體管理機制和調優手段 記憶體管理機制 引用計數、垃圾回收、記憶體池 引用計數 引用計數是一種非常高效的記憶體管理手段,當一個python物件被引用時,其引用計數加1,當其不再被一個變數引用時則引用計數減1,當引用計數等於0時物件被刪除。 1. 引用計數

深入理解JVM筆記記憶體管理機制

執行時資料區域 程式計數器 每個執行緒都有一個程式計數器(PC),是當前執行緒所執行的位元組碼的行號指示器,通過改變程式計數器的值來選取下一條指令。各執行緒之間的計數器互不影響,是執行緒私有的記憶體。  如果執行緒執行的是一個JAVA方法,則計數器記錄的為正在執行的位

從零開始的jvm記憶體管理機制

該篇源自於對《深入理解java虛擬機器》的學習和總結。大牛拍磚請輕點。 1、執行時資料區域 1.1 程式計數器 定義:當前執行緒所執行的位元組碼的行號指示器。 設計目的:為了執行緒切換後能恢復到正確的執行位置,所以需要每個執行緒都擁有一個獨立的程式計數器。 注意: a、

【淺析】Python記憶體管理機制

python的記憶體管理分為三個方面: 引用計數 垃圾回收 記憶體池機制 淺析引用計數 python內部使用引用計數,來保持追蹤記憶體中的物件,Python內部記錄了物件有多少個引用,即引用計數,當物件被建立時就建立了一個引用計數,當物件不再需要時,這個物件的引用計

Python記憶體管理機制及調優手段?

記憶體管理機制:引用計數、垃圾回收、記憶體池。 一、引用計數:     引用計數是一種非常高效的記憶體管理手段, 當一個 Python 物件被引用時其引用計數增加 1, 當其不再被一個變數引用時則計數減 1. 當引用計數等於 0 時物件被刪除。 二、垃圾回收 : 1. 引用計

Python記憶體管理機制

從三個方面來說;一、物件的引用計數機制; 二、垃圾回收機制; 三、記憶體池機制一、物件的引用計數機制Python內部使用引用計數,來保持追蹤記憶體中的物件,所有物件都有引用計數。引用計數增加的情況:1,一個物件分配一個新名稱2,將其放入一個容器中(如列表、元組或字典)引用計數

python記憶體管理機制

先從較淺的層面來說,Python的記憶體管理機制可以從三個方面來講 (1)垃圾回收 (2)引用計數 (3)記憶體池機制 一、垃圾回收: python不像C++,Java等語言一樣,他們可以不用事先宣告變數型別而直接對變數進行賦值。對Python語言來講,物件的型別和記憶體都是在執行時確定的。這也是為

Python記憶體管理機制及調優手段?

記憶體管理機制:引用計數、垃圾回收、記憶體池。引用計數:         引用計數是一種垃圾收集機制,而且也是一種最直觀,最簡單的垃圾收集技術。當 Python 的某個物件的引用計數降為 0 時,說明沒有任何引用指向該物件,該物件就成為要被回收的垃圾了。比如某個新建物件,它被

Android學習 記憶體管理機制與應用記憶體優化

    Random Access Memory(RAM)在任何軟體開發環境中都是一個很寶貴的資源。這一點在實體記憶體通常很有限的移動作業系統上,顯得尤為突出。儘管Android的Dalvik虛擬機器扮演了常規的垃圾回收的角色,但這並不意味著你可以忽視app的記憶體分配與釋放的時機與地點。於大多數apps來說

Python記憶體管理機制(一 小記憶體塊的申請)

哈哈哈,看的有點兒興奮了,筆記下:       在Python的內部同時維護著巨集和記憶體管理函式兩種記憶體管理機制,巨集定義可以節省一次函式呼叫的開銷, 提高執行效率,但同時,使用巨集是危險的,因為隨著Python的演進,記憶體管理機制的實現可能會發生改變,因為巨集

[jjzhu學java]深入理解JVM筆記記憶體管理機制

深入理解JVM筆記之記憶體管理機制 執行時資料區域 程式計數器 每個執行緒都有一個程式計數器(PC),是當前執行緒所執行的位元組碼的行號指示器,通過改變程式計數器的值來選取下一條指令。各執行緒之間的計數器互不影響,是執行緒私有的記憶體。

python深入python記憶體管理機制(重點)

關於python的儲存問題 (1)由於python中萬物皆物件,所以python的儲存問題是物件的儲存問題,並且對於每個物件,python會分配一塊記憶體空間去儲存它 (2)對於整數和短小的字元等,python會執行快取機制,即將這些物件進行快取,不會為相同的物件分配多個

深入理解java虛擬機器自動記憶體管理機制(二)

垃圾收集演算法     java中的記憶體是交給虛擬機器管理的。要實現垃圾回收,必須考慮如下三個問題:     1. 哪些記憶體需要回收?     2. 什麼時候回收?     3. 怎麼回收?     對於第一點,往大了來說,是堆和方法區的記憶體需要回收。往具體了來說,是堆中哪些物件的記憶體可以回

深入理解java虛擬機器自動記憶體管理機制(三)

  各類垃圾收集器與GC日誌 (一)垃圾收集器   一、Serial收集器     最基本、歷史最悠久的收集器。使用複製演算法,用在新生代,通常老年代用Serial old配合。GC過程需要stop the world。適用於client模式下的虛擬機器。   二、ParNew收集器  

深入理解java虛擬機器自動記憶體管理機制(四)

記憶體分配與回收策略 (一)記憶體分配策略     給誰分配?分配到哪?是記憶體分配策略必須解答的問題。     java物件是分配的物件,往大方向來說,是分配到堆中,更細一點說,根據物件不同的特點分配到新生代和老年代區域。如果啟動了本地執行緒分配緩衝,就按執行緒優先在TLAB上分配。     一、新

python記憶體管理機制

python的記憶體管理機制:引用計數、垃圾回收、記憶體池機制 一 變數和物件 1、Python快取了整數和短字串,因此每個物件在記憶體中只存有一份,引用所指物件就是相同的,即使使用賦值語句,也只是

Java的記憶體管理機制記憶體區域劃分

      各位,好久不見。先做個預告,由於最近主要在做Java服務端開發,最近一段時間會更新Java服務端開發相關的一些知識,包括但不限於一些讀書筆記、框架的學習筆記、和最近一段時間的思考和沉澱。先從Java虛擬機器的記憶體開始吧。 Java虛擬機器在執行Java

資料結構動態記憶體管理機制

通過前面的學習,介紹很多具體的資料結構的儲存以及遍歷的方式,過程中只是很表面地介紹了資料的儲存,而沒有涉及到更底層的有關的儲存空間的分配與回收,從本節開始將做更深入地介紹。 在使用早期的計算機上編寫程式時,有關資料儲存在什麼位置等這樣的問題都是需要程式設計師自己來給資料分配記憶體。而現在的高階語言,大大的

cocos2dx學習路----第十四篇(記憶體管理機制

本來這一篇要繼續詳談一下動作類相關的應用,但是考慮到思路差不多,只是呼叫的類方法名引數不一樣而已。到時候再通過一個小的案例來進一步熟悉學習相關介面的使用。這一篇就來談談另外一個比較重要的類,引用計數類(Ref)。 關於cocos2dx這一套記憶體管理,它是引用了object